lightview 2.3.4 → 2.3.6

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/lightview-all.js CHANGED
@@ -587,6 +587,11 @@
587
587
  const makeReactiveAttributes = (attributes, domNode) => {
588
588
  const reactiveAttrs = {};
589
589
  for (let [key, value] of Object.entries(attributes)) {
590
+ if (value && typeof value === "object" && value.__xpath__ && value.__static__) {
591
+ domNode.setAttribute(`data-xpath-${key}`, value.__xpath__);
592
+ reactiveAttrs[key] = value;
593
+ continue;
594
+ }
590
595
  if (key === "onmount" || key === "onunmount") {
591
596
  const state2 = getOrSet(nodeState, domNode, nodeStateFactory);
592
597
  state2[key] = value;
@@ -640,6 +645,7 @@
640
645
  return reactiveAttrs;
641
646
  };
642
647
  const processChildren = (children, targetNode, clearExisting = true) => {
648
+ var _a2;
643
649
  if (clearExisting && targetNode.innerHTML !== void 0) {
644
650
  targetNode.innerHTML = "";
645
651
  }
@@ -688,6 +694,11 @@
688
694
  runner = effect(update);
689
695
  trackEffect(startMarker, runner);
690
696
  childElements.push(child);
697
+ } else if (child && typeof child === "object" && child.__xpath__ && child.__static__) {
698
+ const textNode = document.createTextNode("");
699
+ textNode.__xpathExpr = child.__xpath__;
700
+ targetNode.appendChild(textNode);
701
+ childElements.push(child);
691
702
  } else if (["string", "number", "boolean", "symbol"].includes(type) || child && type === "object" && child instanceof String) {
692
703
  targetNode.appendChild(document.createTextNode(child));
693
704
  childElements.push(child);
@@ -707,6 +718,9 @@
707
718
  childElements.push(childEl);
708
719
  }
709
720
  }
721
+ if (typeof ((_a2 = globalThis.LightviewCDOM) == null ? void 0 : _a2.resolveStaticXPath) === "function") {
722
+ globalThis.LightviewCDOM.resolveStaticXPath(targetNode);
723
+ }
710
724
  return childElements;
711
725
  };
712
726
  const setupChildrenInTarget = (children, targetNode) => {
@@ -1297,14 +1311,15 @@
1297
1311
  }
1298
1312
  };
1299
1313
  const parseElements = (content, isJson, isHtml, el, element2, isCdom = false, ext = "") => {
1300
- var _a2;
1301
1314
  if (isJson) return Array.isArray(content) ? content : [content];
1302
1315
  if (isCdom && ext === "cdomc") {
1303
- const parser = (_a2 = globalThis.LightviewCDOM) == null ? void 0 : _a2.parseCDOMC;
1316
+ const CDOM = globalThis.LightviewCDOM;
1317
+ const parser = CDOM == null ? void 0 : CDOM.parseCDOMC;
1304
1318
  if (parser) {
1305
1319
  try {
1306
1320
  const obj = parser(content);
1307
- return Array.isArray(obj) ? obj : [obj];
1321
+ const hydrated = CDOM.hydrate ? CDOM.hydrate(obj) : obj;
1322
+ return Array.isArray(hydrated) ? hydrated : [hydrated];
1308
1323
  } catch (e) {
1309
1324
  console.warn("LightviewX: Failed to parse .cdomc:", e);
1310
1325
  return [];
@@ -2189,7 +2204,7 @@
2189
2204
  }
2190
2205
  if (options) helperOptions.set(name, options);
2191
2206
  };
2192
- const registerOperator = (helperName, symbol, position, precedence) => {
2207
+ const registerOperator = (helperName, symbol, position, precedence, options = {}) => {
2193
2208
  var _a2;
2194
2209
  if (!["prefix", "postfix", "infix"].includes(position)) {
2195
2210
  throw new Error(`Invalid operator position: ${position}. Must be 'prefix', 'postfix', or 'infix'.`);
@@ -2198,7 +2213,7 @@
2198
2213
  (_a2 = globalThis.console) == null ? void 0 : _a2.warn(`LightviewCDOM: Operator "${symbol}" registered for helper "${helperName}" which is not yet registered.`);
2199
2214
  }
2200
2215
  const prec = precedence ?? DEFAULT_PRECEDENCE[position];
2201
- operators[position].set(symbol, { helper: helperName, precedence: prec });
2216
+ operators[position].set(symbol, { helper: helperName, precedence: prec, options });
2202
2217
  };
2203
2218
  const getLV = () => globalThis.Lightview || null;
2204
2219
  const getRegistry = () => {
@@ -2260,12 +2275,13 @@
2260
2275
  if (typeof path !== "string") return path;
2261
2276
  const registry2 = getRegistry();
2262
2277
  if (path === ".") return unwrapSignal(context);
2263
- if (path.startsWith("=/")) {
2264
- const [rootName, ...rest] = path.slice(2).split("/");
2278
+ if (path.startsWith("=/") || path.startsWith("/")) {
2279
+ const segments = path.startsWith("=/") ? path.slice(2).split("/") : path.slice(1).split("/");
2280
+ const rootName = segments.shift();
2265
2281
  const LV = getLV();
2266
2282
  const root = LV ? LV.get(rootName, { scope: (context == null ? void 0 : context.__node__) || context }) : registry2 == null ? void 0 : registry2.get(rootName);
2267
2283
  if (!root) return void 0;
2268
- return traverse(root, rest);
2284
+ return traverse(root, segments);
2269
2285
  }
2270
2286
  if (path.startsWith("./")) {
2271
2287
  return traverse(context, path.slice(2).split("/"));
@@ -2274,6 +2290,10 @@
2274
2290
  return traverse(context == null ? void 0 : context.__parent__, path.slice(3).split("/"));
2275
2291
  }
2276
2292
  if (path.includes("/") || path.includes(".")) {
2293
+ const unwrapped = unwrapSignal(context);
2294
+ if (unwrapped && typeof unwrapped === "object" && path in unwrapped) {
2295
+ return unwrapSignal(unwrapped[path]);
2296
+ }
2277
2297
  return traverse(context, path.split(/[\/.]/));
2278
2298
  }
2279
2299
  const unwrappedContext = unwrapSignal(context);
@@ -2288,8 +2308,8 @@
2288
2308
  if (typeof path !== "string") return path;
2289
2309
  const registry2 = getRegistry();
2290
2310
  if (path === ".") return context;
2291
- if (path.startsWith("=/")) {
2292
- const segments = path.slice(2).split(/[/.]/);
2311
+ if (path.startsWith("=/") || path.startsWith("/")) {
2312
+ const segments = path.startsWith("=/") ? path.slice(2).split(/[/.]/) : path.slice(1).split(/[/.]/);
2293
2313
  const rootName = segments.shift();
2294
2314
  const LV = getLV();
2295
2315
  const root = LV ? LV.get(rootName, { scope: (context == null ? void 0 : context.__node__) || context }) : registry2 == null ? void 0 : registry2.get(rootName);
@@ -2303,6 +2323,10 @@
2303
2323
  return traverseAsContext(context == null ? void 0 : context.__parent__, path.slice(3).split(/[\/.]/));
2304
2324
  }
2305
2325
  if (path.includes("/") || path.includes(".")) {
2326
+ const unwrapped = unwrapSignal(context);
2327
+ if (unwrapped && typeof unwrapped === "object" && path in unwrapped) {
2328
+ return new BindingTarget(unwrapped, path);
2329
+ }
2306
2330
  return traverseAsContext(context, path.split(/[\/.]/));
2307
2331
  }
2308
2332
  const unwrappedContext = unwrapSignal(context);
@@ -2371,7 +2395,7 @@
2371
2395
  const resolveTemplate = (node, context2) => {
2372
2396
  if (typeof node === "string") {
2373
2397
  if (node.startsWith("=")) {
2374
- const res = resolveExpression(node, context2);
2398
+ const res = resolveExpression$1(node, context2);
2375
2399
  const final = res instanceof LazyValue ? res.resolve(context2) : res;
2376
2400
  return unwrapSignal(final);
2377
2401
  }
@@ -2427,7 +2451,7 @@
2427
2451
  } else if (globalMode && !arg.startsWith("=") && !arg.startsWith("./")) {
2428
2452
  nestedExpr = `=/${arg}`;
2429
2453
  }
2430
- const val = resolveExpression(nestedExpr, context);
2454
+ const val = resolveExpression$1(nestedExpr, context);
2431
2455
  if (val instanceof LazyValue) {
2432
2456
  return { value: val, isLazy: true };
2433
2457
  }
@@ -2488,6 +2512,16 @@
2488
2512
  // $this
2489
2513
  EVENT: "EVENT",
2490
2514
  // $event, $event.target
2515
+ LBRACE: "LBRACE",
2516
+ // {
2517
+ RBRACE: "RBRACE",
2518
+ // }
2519
+ LBRACKET: "LBRACKET",
2520
+ // [
2521
+ RBRACKET: "RBRACKET",
2522
+ // ]
2523
+ COLON: "COLON",
2524
+ // :
2491
2525
  EOF: "EOF"
2492
2526
  };
2493
2527
  const getOperatorSymbols = () => {
@@ -2499,6 +2533,7 @@
2499
2533
  return [...allOps].sort((a, b) => b.length - a.length);
2500
2534
  };
2501
2535
  const tokenize = (expr) => {
2536
+ var _a2, _b2;
2502
2537
  const tokens = [];
2503
2538
  let i = 0;
2504
2539
  const len2 = expr.length;
@@ -2508,16 +2543,21 @@
2508
2543
  i++;
2509
2544
  continue;
2510
2545
  }
2511
- if (expr[i] === "=" && i + 1 < len2) {
2546
+ if (expr[i] === "=" && i === 0 && i + 1 < len2) {
2512
2547
  const prefixOps = [...operators.prefix.keys()].sort((a, b) => b.length - a.length);
2513
- let isPrefixOp = false;
2548
+ let matchedPrefix = null;
2514
2549
  for (const op of prefixOps) {
2515
2550
  if (expr.slice(i + 1, i + 1 + op.length) === op) {
2516
- isPrefixOp = true;
2551
+ matchedPrefix = op;
2517
2552
  break;
2518
2553
  }
2519
2554
  }
2520
- if (isPrefixOp) {
2555
+ if (matchedPrefix) {
2556
+ i++;
2557
+ continue;
2558
+ }
2559
+ const next = expr[i + 1];
2560
+ if (next === "/" || next === "." || /[a-zA-Z_$]/.test(next)) {
2521
2561
  i++;
2522
2562
  continue;
2523
2563
  }
@@ -2537,20 +2577,52 @@
2537
2577
  i++;
2538
2578
  continue;
2539
2579
  }
2580
+ if (expr[i] === "{") {
2581
+ tokens.push({ type: TokenType.LBRACE, value: "{" });
2582
+ i++;
2583
+ continue;
2584
+ }
2585
+ if (expr[i] === "}") {
2586
+ tokens.push({ type: TokenType.RBRACE, value: "}" });
2587
+ i++;
2588
+ continue;
2589
+ }
2590
+ if (expr[i] === "[") {
2591
+ tokens.push({ type: TokenType.LBRACKET, value: "[" });
2592
+ i++;
2593
+ continue;
2594
+ }
2595
+ if (expr[i] === "]") {
2596
+ tokens.push({ type: TokenType.RBRACKET, value: "]" });
2597
+ i++;
2598
+ continue;
2599
+ }
2600
+ if (expr[i] === ":") {
2601
+ tokens.push({ type: TokenType.COLON, value: ":" });
2602
+ i++;
2603
+ continue;
2604
+ }
2540
2605
  let matchedOp = null;
2541
2606
  for (const op of opSymbols) {
2542
2607
  if (expr.slice(i, i + op.length) === op) {
2543
2608
  const before = i > 0 ? expr[i - 1] : " ";
2544
2609
  const after = i + op.length < len2 ? expr[i + op.length] : " ";
2545
- const isInfix = operators.infix.has(op);
2546
- const isPrefix = operators.prefix.has(op);
2547
- const isPostfix = operators.postfix.has(op);
2548
- if (isInfix && !isPrefix && !isPostfix) {
2549
- if (/\s/.test(before) && /\s/.test(after)) {
2610
+ const infixConf = operators.infix.get(op);
2611
+ const prefixConf = operators.prefix.get(op);
2612
+ const postfixConf = operators.postfix.get(op);
2613
+ if ((_a2 = infixConf == null ? void 0 : infixConf.options) == null ? void 0 : _a2.requiresWhitespace) {
2614
+ if (!prefixConf && !postfixConf) {
2615
+ const isWhitespaceMatch = /\s/.test(before) && /\s/.test(after);
2616
+ if (!isWhitespaceMatch) continue;
2617
+ }
2618
+ }
2619
+ if (infixConf) {
2620
+ const lastTok = tokens[tokens.length - 1];
2621
+ const isValueContext = lastTok && (lastTok.type === TokenType.PATH || lastTok.type === TokenType.LITERAL || lastTok.type === TokenType.RPAREN || lastTok.type === TokenType.PLACEHOLDER || lastTok.type === TokenType.THIS || lastTok.type === TokenType.EVENT);
2622
+ if (isValueContext) {
2550
2623
  matchedOp = op;
2551
2624
  break;
2552
2625
  }
2553
- continue;
2554
2626
  }
2555
2627
  const validBefore = /[\s)]/.test(before) || i === 0 || tokens.length === 0 || tokens[tokens.length - 1].type === TokenType.LPAREN || tokens[tokens.length - 1].type === TokenType.COMMA || tokens[tokens.length - 1].type === TokenType.OPERATOR;
2556
2628
  const validAfter = /[\s(=./'"0-9_]/.test(after) || i + op.length >= len2 || opSymbols.some((o) => expr.slice(i + op.length).startsWith(o));
@@ -2635,16 +2707,18 @@
2635
2707
  let isOp = false;
2636
2708
  for (const op of opSymbols) {
2637
2709
  if (expr.slice(i, i + op.length) === op) {
2638
- const isInfix = operators.infix.has(op);
2639
- const isPrefix = operators.prefix.has(op);
2640
- const isPostfix = operators.postfix.has(op);
2641
- if (isInfix && !isPrefix && !isPostfix) {
2642
- const after = i + op.length < len2 ? expr[i + op.length] : " ";
2643
- if (/\s/.test(expr[i - 1]) && /\s/.test(after)) {
2644
- isOp = true;
2645
- break;
2710
+ const infixConf = operators.infix.get(op);
2711
+ const prefixConf = operators.prefix.get(op);
2712
+ const postfixConf = operators.postfix.get(op);
2713
+ if ((_b2 = infixConf == null ? void 0 : infixConf.options) == null ? void 0 : _b2.requiresWhitespace) {
2714
+ if (!prefixConf && !postfixConf) {
2715
+ const after = i + op.length < len2 ? expr[i + op.length] : " ";
2716
+ if (/\s/.test(expr[i - 1]) && /\s/.test(after)) {
2717
+ isOp = true;
2718
+ break;
2719
+ }
2720
+ continue;
2646
2721
  }
2647
- continue;
2648
2722
  }
2649
2723
  if (path.length > 0 && path[path.length - 1] !== "/") {
2650
2724
  isOp = true;
@@ -2688,14 +2762,16 @@
2688
2762
  };
2689
2763
  const hasOperatorSyntax = (expr) => {
2690
2764
  if (!expr || typeof expr !== "string") return false;
2691
- if (expr.includes("(")) return false;
2692
- if (/^=(\+\+|--|!!)\/?/.test(expr)) {
2765
+ if (/^=?(\+\+|--|!!)\/?/.test(expr)) {
2693
2766
  return true;
2694
2767
  }
2695
2768
  if (/(\+\+|--)$/.test(expr)) {
2696
2769
  return true;
2697
2770
  }
2698
- if (/\s+([+\-*/]|>|<|>=|<=|!=)\s+/.test(expr)) {
2771
+ if (/\s+([+\-*/%]|>|<|>=|<=|!=|===|==|=)\s+/.test(expr)) {
2772
+ return true;
2773
+ }
2774
+ if (/[^=\s]([+%=]|==|===|!=|!==|<=|>=|<|>)[^=\s]/.test(expr)) {
2699
2775
  return true;
2700
2776
  }
2701
2777
  return false;
@@ -2807,15 +2883,71 @@
2807
2883
  this.consume();
2808
2884
  return { type: "Explosion", path: tok.value };
2809
2885
  }
2886
+ if (nextTok.type === TokenType.LPAREN) {
2887
+ this.consume();
2888
+ const args = [];
2889
+ while (this.peek().type !== TokenType.RPAREN && this.peek().type !== TokenType.EOF) {
2890
+ args.push(this.parseExpression(0));
2891
+ if (this.peek().type === TokenType.COMMA) {
2892
+ this.consume();
2893
+ }
2894
+ }
2895
+ this.expect(TokenType.RPAREN);
2896
+ return { type: "Call", helper: tok.value, args };
2897
+ }
2810
2898
  return { type: "Path", value: tok.value };
2811
2899
  }
2900
+ if (tok.type === TokenType.LBRACE) {
2901
+ return this.parseObjectLiteral();
2902
+ }
2903
+ if (tok.type === TokenType.LBRACKET) {
2904
+ return this.parseArrayLiteral();
2905
+ }
2812
2906
  if (tok.type === TokenType.EOF) {
2813
2907
  return { type: "Literal", value: void 0 };
2814
2908
  }
2815
2909
  throw new Error(`JPRX: Unexpected token ${tok.type}: ${tok.value}`);
2816
2910
  }
2911
+ parseObjectLiteral() {
2912
+ this.consume();
2913
+ const properties = {};
2914
+ while (this.peek().type !== TokenType.RBRACE && this.peek().type !== TokenType.EOF) {
2915
+ const keyTok = this.consume();
2916
+ let key;
2917
+ if (keyTok.type === TokenType.LITERAL) key = String(keyTok.value);
2918
+ else if (keyTok.type === TokenType.PATH) key = keyTok.value;
2919
+ else if (keyTok.type === TokenType.PATH) key = keyTok.value;
2920
+ else throw new Error(`JPRX: Expected property name but got ${keyTok.type}`);
2921
+ this.expect(TokenType.COLON);
2922
+ const value = this.parseExpression(0);
2923
+ properties[key] = value;
2924
+ if (this.peek().type === TokenType.COMMA) {
2925
+ this.consume();
2926
+ } else if (this.peek().type !== TokenType.RBRACE) {
2927
+ break;
2928
+ }
2929
+ }
2930
+ this.expect(TokenType.RBRACE);
2931
+ return { type: "ObjectLiteral", properties };
2932
+ }
2933
+ parseArrayLiteral() {
2934
+ this.consume();
2935
+ const elements = [];
2936
+ while (this.peek().type !== TokenType.RBRACKET && this.peek().type !== TokenType.EOF) {
2937
+ const value = this.parseExpression(0);
2938
+ elements.push(value);
2939
+ if (this.peek().type === TokenType.COMMA) {
2940
+ this.consume();
2941
+ } else if (this.peek().type !== TokenType.RBRACKET) {
2942
+ break;
2943
+ }
2944
+ }
2945
+ this.expect(TokenType.RBRACKET);
2946
+ return { type: "ArrayLiteral", elements };
2947
+ }
2817
2948
  }
2818
2949
  const evaluateAST = (ast, context, forMutation = false) => {
2950
+ var _a2;
2819
2951
  if (!ast) return void 0;
2820
2952
  switch (ast.type) {
2821
2953
  case "Literal":
@@ -2847,54 +2979,126 @@
2847
2979
  return resolvePath(path, event);
2848
2980
  });
2849
2981
  }
2850
- case "Explosion": {
2851
- const result = resolveArgument(ast.path + "...", context, false);
2852
- return result.value;
2982
+ case "ObjectLiteral": {
2983
+ const res = {};
2984
+ let hasLazy = false;
2985
+ for (const key in ast.properties) {
2986
+ const val = evaluateAST(ast.properties[key], context, forMutation);
2987
+ if (val && val.isLazy) hasLazy = true;
2988
+ res[key] = val;
2989
+ }
2990
+ if (hasLazy) {
2991
+ return new LazyValue((ctx) => {
2992
+ const resolved = {};
2993
+ for (const key in res) {
2994
+ resolved[key] = res[key] && res[key].isLazy ? res[key].resolve(ctx) : unwrapSignal(res[key]);
2995
+ }
2996
+ return resolved;
2997
+ });
2998
+ }
2999
+ return res;
3000
+ }
3001
+ case "ArrayLiteral": {
3002
+ const elements = ast.elements.map((el) => evaluateAST(el, context, forMutation));
3003
+ const hasLazy = elements.some((el) => el && el.isLazy);
3004
+ if (hasLazy) {
3005
+ return new LazyValue((ctx) => {
3006
+ return elements.map((el) => el && el.isLazy ? el.resolve(ctx) : unwrapSignal(el));
3007
+ });
3008
+ }
3009
+ return elements.map((el) => unwrapSignal(el));
2853
3010
  }
2854
3011
  case "Prefix": {
2855
3012
  const opInfo = operators.prefix.get(ast.operator);
2856
- if (!opInfo) {
2857
- throw new Error(`JPRX: Unknown prefix operator: ${ast.operator}`);
2858
- }
3013
+ if (!opInfo) throw new Error(`JPRX: Unknown prefix operator: ${ast.operator}`);
2859
3014
  const helper = helpers.get(opInfo.helper);
2860
- if (!helper) {
2861
- throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
2862
- }
3015
+ if (!helper) throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
2863
3016
  const opts = helperOptions.get(opInfo.helper) || {};
2864
3017
  const operand = evaluateAST(ast.operand, context, opts.pathAware);
2865
- return helper(operand);
3018
+ if (operand && operand.isLazy && !opts.lazyAware) {
3019
+ return new LazyValue((ctx) => {
3020
+ const resolved = operand.resolve(ctx);
3021
+ return helper(opts.pathAware ? resolved : unwrapSignal(resolved));
3022
+ });
3023
+ }
3024
+ return helper(opts.pathAware ? operand : unwrapSignal(operand));
2866
3025
  }
2867
3026
  case "Postfix": {
2868
3027
  const opInfo = operators.postfix.get(ast.operator);
2869
- if (!opInfo) {
2870
- throw new Error(`JPRX: Unknown postfix operator: ${ast.operator}`);
2871
- }
3028
+ if (!opInfo) throw new Error(`JPRX: Unknown postfix operator: ${ast.operator}`);
2872
3029
  const helper = helpers.get(opInfo.helper);
2873
- if (!helper) {
2874
- throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
2875
- }
3030
+ if (!helper) throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
2876
3031
  const opts = helperOptions.get(opInfo.helper) || {};
2877
3032
  const operand = evaluateAST(ast.operand, context, opts.pathAware);
2878
- return helper(operand);
3033
+ if (operand && operand.isLazy && !opts.lazyAware) {
3034
+ return new LazyValue((ctx) => {
3035
+ const resolved = operand.resolve(ctx);
3036
+ return helper(opts.pathAware ? resolved : unwrapSignal(resolved));
3037
+ });
3038
+ }
3039
+ return helper(opts.pathAware ? operand : unwrapSignal(operand));
2879
3040
  }
2880
3041
  case "Infix": {
2881
3042
  const opInfo = operators.infix.get(ast.operator);
2882
- if (!opInfo) {
2883
- throw new Error(`JPRX: Unknown infix operator: ${ast.operator}`);
2884
- }
3043
+ if (!opInfo) throw new Error(`JPRX: Unknown infix operator: ${ast.operator}`);
2885
3044
  const helper = helpers.get(opInfo.helper);
2886
- if (!helper) {
2887
- throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
2888
- }
3045
+ if (!helper) throw new Error(`JPRX: Helper "${opInfo.helper}" for operator "${ast.operator}" not found.`);
2889
3046
  const opts = helperOptions.get(opInfo.helper) || {};
2890
3047
  const left = evaluateAST(ast.left, context, opts.pathAware);
2891
3048
  const right = evaluateAST(ast.right, context, false);
3049
+ if ((left && left.isLazy || right && right.isLazy) && !opts.lazyAware) {
3050
+ return new LazyValue((ctx) => {
3051
+ const l = left && left.isLazy ? left.resolve(ctx) : left;
3052
+ const r = right && right.isLazy ? right.resolve(ctx) : right;
3053
+ return helper(opts.pathAware ? l : unwrapSignal(l), unwrapSignal(r));
3054
+ });
3055
+ }
3056
+ return helper(opts.pathAware ? left : unwrapSignal(left), unwrapSignal(right));
3057
+ }
3058
+ case "Call": {
3059
+ const helperName = ast.helper.replace(/^=/, "");
3060
+ const helper = helpers.get(helperName);
3061
+ if (!helper) {
3062
+ (_a2 = globalThis.console) == null ? void 0 : _a2.warn(`JPRX: Helper "${helperName}" not found.`);
3063
+ return void 0;
3064
+ }
3065
+ const opts = helperOptions.get(helperName) || {};
3066
+ const args = ast.args.map((arg, i) => evaluateAST(arg, context, opts.pathAware && i === 0));
3067
+ const hasLazy = args.some((arg) => arg && arg.isLazy);
3068
+ if (hasLazy && !opts.lazyAware) {
3069
+ return new LazyValue((ctx) => {
3070
+ const finalArgs2 = args.map((arg, i) => {
3071
+ const val = arg && arg.isLazy ? arg.resolve(ctx) : arg;
3072
+ if (ast.args[i].type === "Explosion" && Array.isArray(val)) {
3073
+ return val.map((v) => unwrapSignal(v));
3074
+ }
3075
+ return opts.pathAware && i === 0 ? val : unwrapSignal(val);
3076
+ });
3077
+ const flatArgs = [];
3078
+ for (let i = 0; i < finalArgs2.length; i++) {
3079
+ if (ast.args[i].type === "Explosion" && Array.isArray(finalArgs2[i])) {
3080
+ flatArgs.push(...finalArgs2[i]);
3081
+ } else {
3082
+ flatArgs.push(finalArgs2[i]);
3083
+ }
3084
+ }
3085
+ return helper.apply((context == null ? void 0 : context.__node__) || null, flatArgs);
3086
+ });
3087
+ }
2892
3088
  const finalArgs = [];
2893
- if (Array.isArray(left) && ast.left.type === "Explosion") finalArgs.push(...left);
2894
- else finalArgs.push(unwrapSignal(left));
2895
- if (Array.isArray(right) && ast.right.type === "Explosion") finalArgs.push(...right);
2896
- else finalArgs.push(unwrapSignal(right));
2897
- return helper(...finalArgs);
3089
+ for (let i = 0; i < args.length; i++) {
3090
+ const arg = args[i];
3091
+ if (ast.args[i].type === "Explosion" && Array.isArray(arg)) {
3092
+ finalArgs.push(...arg.map((v) => unwrapSignal(v)));
3093
+ } else {
3094
+ finalArgs.push(opts.pathAware && i === 0 ? arg : unwrapSignal(arg));
3095
+ }
3096
+ }
3097
+ return helper.apply((context == null ? void 0 : context.__node__) || null, finalArgs);
3098
+ }
3099
+ case "Explosion": {
3100
+ const result = resolveArgument(ast.path + "...", context, false);
3101
+ return result.value;
2898
3102
  }
2899
3103
  default:
2900
3104
  throw new Error(`JPRX: Unknown AST node type: ${ast.type}`);
@@ -2906,7 +3110,7 @@
2906
3110
  const ast = parser.parseExpression(0);
2907
3111
  return evaluateAST(ast, context);
2908
3112
  };
2909
- const resolveExpression = (expr, context) => {
3113
+ const resolveExpression$1 = (expr, context) => {
2910
3114
  var _a2, _b2;
2911
3115
  if (typeof expr !== "string") return expr;
2912
3116
  if (hasOperatorSyntax(expr)) {
@@ -2993,7 +3197,7 @@
2993
3197
  const parseExpression = (expr, context) => {
2994
3198
  const LV = getLV();
2995
3199
  if (!LV || typeof expr !== "string") return expr;
2996
- return LV.computed(() => resolveExpression(expr, context));
3200
+ return LV.computed(() => resolveExpression$1(expr, context));
2997
3201
  };
2998
3202
  const parseCDOMC = (input) => {
2999
3203
  let i = 0;
@@ -3052,10 +3256,12 @@
3052
3256
  let bDepth = 0;
3053
3257
  let brDepth = 0;
3054
3258
  let quote = null;
3259
+ const startChar = input[start];
3260
+ const isExpression = startChar === "=" || startChar === "#";
3055
3261
  while (i < len2) {
3056
3262
  const char = input[i];
3057
3263
  if (quote) {
3058
- if (char === quote) quote = null;
3264
+ if (char === quote && input[i - 1] !== "\\") quote = null;
3059
3265
  i++;
3060
3266
  continue;
3061
3267
  } else if (char === '"' || char === "'" || char === "`") {
@@ -3100,14 +3306,41 @@
3100
3306
  }
3101
3307
  }
3102
3308
  if (pDepth === 0 && bDepth === 0 && brDepth === 0) {
3103
- if (/[\s:,{}\[\]"'`()]/.test(char)) {
3104
- break;
3309
+ if (isExpression) {
3310
+ if (/[{}[\]"'`()]/.test(char)) {
3311
+ break;
3312
+ }
3313
+ if (char === ",") {
3314
+ break;
3315
+ }
3316
+ if (/[\s:]/.test(char)) {
3317
+ let j = i + 1;
3318
+ while (j < len2 && /\s/.test(input[j])) j++;
3319
+ if (j < len2) {
3320
+ const nextChar = input[j];
3321
+ if (nextChar === "}" || nextChar === ",") {
3322
+ break;
3323
+ }
3324
+ let wordStart = j;
3325
+ while (j < len2 && /[a-zA-Z0-9_$-]/.test(input[j])) j++;
3326
+ if (j > wordStart) {
3327
+ while (j < len2 && /\s/.test(input[j])) j++;
3328
+ if (j < len2 && input[j] === ":") {
3329
+ break;
3330
+ }
3331
+ }
3332
+ }
3333
+ }
3334
+ } else {
3335
+ if (/[:,{}[\]"'`()\s]/.test(char)) {
3336
+ break;
3337
+ }
3105
3338
  }
3106
3339
  }
3107
3340
  i++;
3108
3341
  }
3109
3342
  const word = input.slice(start, i);
3110
- if (word.startsWith("=")) {
3343
+ if (word.startsWith("=") || word.startsWith("#")) {
3111
3344
  return word;
3112
3345
  }
3113
3346
  if (word === "true") return true;
@@ -3259,7 +3492,26 @@
3259
3492
  inExprQuote = c;
3260
3493
  } else {
3261
3494
  if (parenDepth === 0 && braceDepth === 0 && bracketDepth === 0) {
3262
- if (/[\s,}\]:]/.test(c) && expr.length > 1) break;
3495
+ if (/[}[\]:]/.test(c) && expr.length > 1) break;
3496
+ if (c === ",") break;
3497
+ if (/\s/.test(c)) {
3498
+ let j = i + 1;
3499
+ while (j < len2 && /\s/.test(input[j])) j++;
3500
+ if (j < len2) {
3501
+ const nextChar = input[j];
3502
+ if (nextChar === "}" || nextChar === "," || nextChar === "]") {
3503
+ break;
3504
+ }
3505
+ let wordStart = j;
3506
+ while (j < len2 && /[a-zA-Z0-9_$-]/.test(input[j])) j++;
3507
+ if (j > wordStart) {
3508
+ while (j < len2 && /\s/.test(input[j])) j++;
3509
+ if (j < len2 && input[j] === ":") {
3510
+ break;
3511
+ }
3512
+ }
3513
+ }
3514
+ }
3263
3515
  }
3264
3516
  if (c === "(") parenDepth++;
3265
3517
  else if (c === ")") parenDepth--;
@@ -3284,6 +3536,32 @@
3284
3536
  while (j < len2 && /\s/.test(input[j])) j++;
3285
3537
  if (input[j] === ":") {
3286
3538
  result += `"${word}"`;
3539
+ } else if (input[j] === "(") {
3540
+ let expr = word;
3541
+ i = j;
3542
+ let parenDepth = 0;
3543
+ let inQuote = null;
3544
+ while (i < len2) {
3545
+ const c = input[i];
3546
+ if (inQuote) {
3547
+ if (c === inQuote && input[i - 1] !== "\\") inQuote = null;
3548
+ } else if (c === '"' || c === "'") {
3549
+ inQuote = c;
3550
+ } else {
3551
+ if (c === "(") parenDepth++;
3552
+ else if (c === ")") {
3553
+ parenDepth--;
3554
+ if (parenDepth === 0) {
3555
+ expr += c;
3556
+ i++;
3557
+ break;
3558
+ }
3559
+ }
3560
+ }
3561
+ expr += c;
3562
+ i++;
3563
+ }
3564
+ result += JSON.stringify("=" + expr);
3287
3565
  } else {
3288
3566
  if (word === "true" || word === "false" || word === "null") {
3289
3567
  result += word;
@@ -3315,7 +3593,7 @@
3315
3593
  throw e;
3316
3594
  }
3317
3595
  };
3318
- const add = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
3596
+ const add$1 = (...args) => args.reduce((a, b) => Number(a) + Number(b), 0);
3319
3597
  const subtract = (a, b) => Number(a) - Number(b);
3320
3598
  const multiply = (...args) => args.reduce((a, b) => Number(a) * Number(b), 1);
3321
3599
  const divide = (a, b) => Number(a) / Number(b);
@@ -3323,12 +3601,14 @@
3323
3601
  const ceil = (val) => Math.ceil(val);
3324
3602
  const floor = (val) => Math.floor(val);
3325
3603
  const abs = (val) => Math.abs(val);
3326
- const mod = (a, b) => a % b;
3604
+ const mod$1 = (a, b) => a % b;
3327
3605
  const pow = (a, b) => Math.pow(a, b);
3328
3606
  const sqrt = (val) => Math.sqrt(val);
3607
+ const negate = (val) => -Number(val);
3608
+ const toPercent = (val) => Number(val) / 100;
3329
3609
  const registerMathHelpers = (register) => {
3330
- register("+", add);
3331
- register("add", add);
3610
+ register("+", add$1);
3611
+ register("add", add$1);
3332
3612
  register("-", subtract);
3333
3613
  register("sub", subtract);
3334
3614
  register("*", multiply);
@@ -3339,16 +3619,20 @@
3339
3619
  register("ceil", ceil);
3340
3620
  register("floor", floor);
3341
3621
  register("abs", abs);
3342
- register("mod", mod);
3622
+ register("mod", mod$1);
3343
3623
  register("pow", pow);
3344
3624
  register("sqrt", sqrt);
3625
+ register("negate", negate);
3626
+ register("toPercent", toPercent);
3345
3627
  };
3346
- const ifHelper = (condition, thenVal, elseVal) => condition ? thenVal : elseVal;
3628
+ const ifHelper = (condition2, thenVal, elseVal) => condition2 ? thenVal : elseVal;
3347
3629
  const andHelper = (...args) => args.every(Boolean);
3348
3630
  const orHelper = (...args) => args.some(Boolean);
3349
3631
  const notHelper = (val) => !val;
3350
- const eqHelper = (a, b) => a === b;
3351
- const neqHelper = (a, b) => a !== b;
3632
+ const eqHelper = (a, b) => a == b;
3633
+ const strictEqHelper = (a, b) => a === b;
3634
+ const neqHelper = (a, b) => a != b;
3635
+ const strictNeqHelper = (a, b) => a !== b;
3352
3636
  const registerLogicHelpers = (register) => {
3353
3637
  register("if", ifHelper);
3354
3638
  register("and", andHelper);
@@ -3358,16 +3642,20 @@
3358
3642
  register("not", notHelper);
3359
3643
  register("!", notHelper);
3360
3644
  register("eq", eqHelper);
3645
+ register("strictEq", strictEqHelper);
3361
3646
  register("==", eqHelper);
3362
- register("===", eqHelper);
3647
+ register("===", strictEqHelper);
3363
3648
  register("neq", neqHelper);
3649
+ register("strictNeq", strictNeqHelper);
3650
+ register("!=", neqHelper);
3651
+ register("!==", strictNeqHelper);
3364
3652
  };
3365
3653
  const join$1 = (...args) => {
3366
3654
  const separator = args[args.length - 1];
3367
3655
  const items = args.slice(0, -1);
3368
3656
  return items.join(separator);
3369
3657
  };
3370
- const concat = (...args) => args.join("");
3658
+ const concat$1 = (...args) => args.join("");
3371
3659
  const upper = (s) => String(s).toUpperCase();
3372
3660
  const lower = (s) => String(s).toLowerCase();
3373
3661
  const trim = (s) => String(s).trim();
@@ -3381,13 +3669,13 @@
3381
3669
  const titleCase = (s) => {
3382
3670
  return String(s).toLowerCase().split(" ").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
3383
3671
  };
3384
- const contains$1 = (s, search) => String(s).includes(search);
3672
+ const contains$2 = (s, search) => String(s).includes(search);
3385
3673
  const startsWith = (s, prefix) => String(s).startsWith(prefix);
3386
3674
  const endsWith = (s, suffix) => String(s).endsWith(suffix);
3387
3675
  const defaultHelper = (val, fallback) => val !== void 0 && val !== null ? val : fallback;
3388
3676
  const registerStringHelpers = (register) => {
3389
3677
  register("join", join$1);
3390
- register("concat", concat);
3678
+ register("concat", concat$1);
3391
3679
  register("upper", upper);
3392
3680
  register("lower", lower);
3393
3681
  register("trim", trim);
@@ -3396,7 +3684,7 @@
3396
3684
  register("split", split);
3397
3685
  register("capitalize", capitalize);
3398
3686
  register("titleCase", titleCase);
3399
- register("contains", contains$1);
3687
+ register("contains", contains$2);
3400
3688
  register("startsWith", startsWith);
3401
3689
  register("endsWith", endsWith);
3402
3690
  register("default", defaultHelper);
@@ -3469,7 +3757,7 @@
3469
3757
  const lte = (a, b) => a <= b;
3470
3758
  const neq = (a, b) => a !== b;
3471
3759
  const between = (val, min2, max2) => val >= min2 && val <= max2;
3472
- const contains = (arr, val) => Array.isArray(arr) && arr.includes(val);
3760
+ const contains$1 = (arr, val) => Array.isArray(arr) && arr.includes(val);
3473
3761
  const registerCompareHelpers = (register) => {
3474
3762
  register("gt", gt);
3475
3763
  register(">", gt);
@@ -3482,7 +3770,7 @@
3482
3770
  register("neq", neq);
3483
3771
  register("!=", neq);
3484
3772
  register("between", between);
3485
- register("in", contains);
3773
+ register("in", contains$1);
3486
3774
  };
3487
3775
  const sumIf = (arr, predicate) => {
3488
3776
  if (!Array.isArray(arr)) return 0;
@@ -3573,16 +3861,35 @@
3573
3861
  };
3574
3862
  const index = (arr, idx) => Array.isArray(arr) ? arr[idx] : void 0;
3575
3863
  const match = (val, arr) => Array.isArray(arr) ? arr.indexOf(val) : -1;
3864
+ const pathRef = (path, context) => {
3865
+ if (path && typeof path === "object" && "value" in path) {
3866
+ return unwrapSignal(path.value);
3867
+ }
3868
+ if (typeof path === "string") {
3869
+ const normalized = path.startsWith("=") ? path : "=" + path;
3870
+ const resolved = resolvePath(normalized, context);
3871
+ const value = unwrapSignal(resolved);
3872
+ if (typeof value === "number") return value;
3873
+ if (typeof value === "string" && value !== "" && !isNaN(parseFloat(value)) && isFinite(Number(value))) {
3874
+ return parseFloat(value);
3875
+ }
3876
+ return value;
3877
+ }
3878
+ return unwrapSignal(path);
3879
+ };
3576
3880
  const registerLookupHelpers = (register) => {
3577
3881
  register("lookup", lookup);
3578
3882
  register("vlookup", vlookup);
3579
3883
  register("index", index);
3580
3884
  register("match", match);
3885
+ register("$", pathRef, { pathAware: true });
3886
+ register("val", pathRef, { pathAware: true });
3887
+ register("indirect", pathRef, { pathAware: true });
3581
3888
  };
3582
3889
  const sum = (...args) => args.reduce((a, b) => a + (Number(b) || 0), 0);
3583
3890
  const avg = (...args) => args.length === 0 ? 0 : sum(...args) / args.length;
3584
- const min = (...args) => Math.min(...args);
3585
- const max = (...args) => Math.max(...args);
3891
+ const min$1 = (...args) => Math.min(...args);
3892
+ const max$1 = (...args) => Math.max(...args);
3586
3893
  const median = (...args) => {
3587
3894
  if (args.length === 0) return 0;
3588
3895
  const sorted = [...args].sort((a, b) => a - b);
@@ -3604,8 +3911,8 @@
3604
3911
  const registerStatsHelpers = (register) => {
3605
3912
  register("sum", sum);
3606
3913
  register("avg", avg);
3607
- register("min", min);
3608
- register("max", max);
3914
+ register("min", min$1);
3915
+ register("max", max$1);
3609
3916
  register("median", median);
3610
3917
  register("stdev", stdev);
3611
3918
  register("var", variance);
@@ -3720,100 +4027,1796 @@
3720
4027
  const registerNetworkHelpers = (register) => {
3721
4028
  register("fetch", fetchHelper);
3722
4029
  };
3723
- registerMathHelpers(registerHelper);
3724
- registerLogicHelpers(registerHelper);
3725
- registerStringHelpers(registerHelper);
3726
- registerArrayHelpers(registerHelper);
3727
- registerCompareHelpers(registerHelper);
3728
- registerConditionalHelpers(registerHelper);
3729
- registerDateTimeHelpers(registerHelper);
3730
- registerFormatHelpers(registerHelper);
3731
- registerLookupHelpers(registerHelper);
3732
- registerStatsHelpers(registerHelper);
3733
- registerStateHelpers((name, fn) => registerHelper(name, fn, { pathAware: true }));
3734
- registerNetworkHelpers(registerHelper);
3735
- registerHelper("move", (selector, location = "beforeend") => {
3736
- return {
3737
- isLazy: true,
3738
- resolve: (eventOrNode) => {
3739
- const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
3740
- const node = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
3741
- if (!(node instanceof Node) || !selector) return;
3742
- const target = document.querySelector(selector);
3743
- if (!target) {
3744
- console.warn(`[Lightview-CDOM] move target not found: ${selector}`);
3745
- return;
4030
+ var INUMBER = "INUMBER";
4031
+ var IOP1 = "IOP1";
4032
+ var IOP2 = "IOP2";
4033
+ var IOP3 = "IOP3";
4034
+ var IVAR = "IVAR";
4035
+ var IVARNAME = "IVARNAME";
4036
+ var IFUNCALL = "IFUNCALL";
4037
+ var IFUNDEF = "IFUNDEF";
4038
+ var IEXPR = "IEXPR";
4039
+ var IEXPREVAL = "IEXPREVAL";
4040
+ var IMEMBER = "IMEMBER";
4041
+ var IENDSTATEMENT = "IENDSTATEMENT";
4042
+ var IARRAY = "IARRAY";
4043
+ function Instruction(type, value) {
4044
+ this.type = type;
4045
+ this.value = value !== void 0 && value !== null ? value : 0;
4046
+ }
4047
+ Instruction.prototype.toString = function() {
4048
+ switch (this.type) {
4049
+ case INUMBER:
4050
+ case IOP1:
4051
+ case IOP2:
4052
+ case IOP3:
4053
+ case IVAR:
4054
+ case IVARNAME:
4055
+ case IENDSTATEMENT:
4056
+ return this.value;
4057
+ case IFUNCALL:
4058
+ return "CALL " + this.value;
4059
+ case IFUNDEF:
4060
+ return "DEF " + this.value;
4061
+ case IARRAY:
4062
+ return "ARRAY " + this.value;
4063
+ case IMEMBER:
4064
+ return "." + this.value;
4065
+ default:
4066
+ return "Invalid Instruction";
4067
+ }
4068
+ };
4069
+ function unaryInstruction(value) {
4070
+ return new Instruction(IOP1, value);
4071
+ }
4072
+ function binaryInstruction(value) {
4073
+ return new Instruction(IOP2, value);
4074
+ }
4075
+ function ternaryInstruction(value) {
4076
+ return new Instruction(IOP3, value);
4077
+ }
4078
+ function simplify(tokens, unaryOps, binaryOps, ternaryOps, values) {
4079
+ var nstack = [];
4080
+ var newexpression = [];
4081
+ var n1, n2, n3;
4082
+ var f;
4083
+ for (var i = 0; i < tokens.length; i++) {
4084
+ var item = tokens[i];
4085
+ var type = item.type;
4086
+ if (type === INUMBER || type === IVARNAME) {
4087
+ if (Array.isArray(item.value)) {
4088
+ nstack.push.apply(nstack, simplify(item.value.map(function(x) {
4089
+ return new Instruction(INUMBER, x);
4090
+ }).concat(new Instruction(IARRAY, item.value.length)), unaryOps, binaryOps, ternaryOps, values));
4091
+ } else {
4092
+ nstack.push(item);
3746
4093
  }
3747
- if (node.id) {
3748
- const escapedId = CSS.escape(node.id);
3749
- if (target.id === node.id && target !== node) {
3750
- target.replaceWith(node);
3751
- return;
4094
+ } else if (type === IVAR && values.hasOwnProperty(item.value)) {
4095
+ item = new Instruction(INUMBER, values[item.value]);
4096
+ nstack.push(item);
4097
+ } else if (type === IOP2 && nstack.length > 1) {
4098
+ n2 = nstack.pop();
4099
+ n1 = nstack.pop();
4100
+ f = binaryOps[item.value];
4101
+ item = new Instruction(INUMBER, f(n1.value, n2.value));
4102
+ nstack.push(item);
4103
+ } else if (type === IOP3 && nstack.length > 2) {
4104
+ n3 = nstack.pop();
4105
+ n2 = nstack.pop();
4106
+ n1 = nstack.pop();
4107
+ if (item.value === "?") {
4108
+ nstack.push(n1.value ? n2.value : n3.value);
4109
+ } else {
4110
+ f = ternaryOps[item.value];
4111
+ item = new Instruction(INUMBER, f(n1.value, n2.value, n3.value));
4112
+ nstack.push(item);
4113
+ }
4114
+ } else if (type === IOP1 && nstack.length > 0) {
4115
+ n1 = nstack.pop();
4116
+ f = unaryOps[item.value];
4117
+ item = new Instruction(INUMBER, f(n1.value));
4118
+ nstack.push(item);
4119
+ } else if (type === IEXPR) {
4120
+ while (nstack.length > 0) {
4121
+ newexpression.push(nstack.shift());
4122
+ }
4123
+ newexpression.push(new Instruction(IEXPR, simplify(item.value, unaryOps, binaryOps, ternaryOps, values)));
4124
+ } else if (type === IMEMBER && nstack.length > 0) {
4125
+ n1 = nstack.pop();
4126
+ nstack.push(new Instruction(INUMBER, n1.value[item.value]));
4127
+ } else {
4128
+ while (nstack.length > 0) {
4129
+ newexpression.push(nstack.shift());
4130
+ }
4131
+ newexpression.push(item);
4132
+ }
4133
+ }
4134
+ while (nstack.length > 0) {
4135
+ newexpression.push(nstack.shift());
4136
+ }
4137
+ return newexpression;
4138
+ }
4139
+ function substitute(tokens, variable, expr) {
4140
+ var newexpression = [];
4141
+ for (var i = 0; i < tokens.length; i++) {
4142
+ var item = tokens[i];
4143
+ var type = item.type;
4144
+ if (type === IVAR && item.value === variable) {
4145
+ for (var j = 0; j < expr.tokens.length; j++) {
4146
+ var expritem = expr.tokens[j];
4147
+ var replitem;
4148
+ if (expritem.type === IOP1) {
4149
+ replitem = unaryInstruction(expritem.value);
4150
+ } else if (expritem.type === IOP2) {
4151
+ replitem = binaryInstruction(expritem.value);
4152
+ } else if (expritem.type === IOP3) {
4153
+ replitem = ternaryInstruction(expritem.value);
4154
+ } else {
4155
+ replitem = new Instruction(expritem.type, expritem.value);
3752
4156
  }
3753
- const existing = target.querySelector(`#${escapedId}`);
3754
- if (existing && existing !== node) {
3755
- existing.replaceWith(node);
3756
- return;
4157
+ newexpression.push(replitem);
4158
+ }
4159
+ } else if (type === IEXPR) {
4160
+ newexpression.push(new Instruction(IEXPR, substitute(item.value, variable, expr)));
4161
+ } else {
4162
+ newexpression.push(item);
4163
+ }
4164
+ }
4165
+ return newexpression;
4166
+ }
4167
+ function evaluate(tokens, expr, values) {
4168
+ var nstack = [];
4169
+ var n1, n2, n3;
4170
+ var f, args, argCount;
4171
+ if (isExpressionEvaluator(tokens)) {
4172
+ return resolveExpression(tokens, values);
4173
+ }
4174
+ var numTokens = tokens.length;
4175
+ for (var i = 0; i < numTokens; i++) {
4176
+ var item = tokens[i];
4177
+ var type = item.type;
4178
+ if (type === INUMBER || type === IVARNAME) {
4179
+ nstack.push(item.value);
4180
+ } else if (type === IOP2) {
4181
+ n2 = nstack.pop();
4182
+ n1 = nstack.pop();
4183
+ if (item.value === "and") {
4184
+ nstack.push(n1 ? !!evaluate(n2, expr, values) : false);
4185
+ } else if (item.value === "or") {
4186
+ nstack.push(n1 ? true : !!evaluate(n2, expr, values));
4187
+ } else if (item.value === "=") {
4188
+ f = expr.binaryOps[item.value];
4189
+ nstack.push(f(n1, evaluate(n2, expr, values), values));
4190
+ } else {
4191
+ f = expr.binaryOps[item.value];
4192
+ nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values)));
4193
+ }
4194
+ } else if (type === IOP3) {
4195
+ n3 = nstack.pop();
4196
+ n2 = nstack.pop();
4197
+ n1 = nstack.pop();
4198
+ if (item.value === "?") {
4199
+ nstack.push(evaluate(n1 ? n2 : n3, expr, values));
4200
+ } else {
4201
+ f = expr.ternaryOps[item.value];
4202
+ nstack.push(f(resolveExpression(n1, values), resolveExpression(n2, values), resolveExpression(n3, values)));
4203
+ }
4204
+ } else if (type === IVAR) {
4205
+ if (item.value in expr.functions) {
4206
+ nstack.push(expr.functions[item.value]);
4207
+ } else if (item.value in expr.unaryOps && expr.parser.isOperatorEnabled(item.value)) {
4208
+ nstack.push(expr.unaryOps[item.value]);
4209
+ } else {
4210
+ var v = values[item.value];
4211
+ if (v !== void 0) {
4212
+ nstack.push(v);
4213
+ } else {
4214
+ throw new Error("undefined variable: " + item.value);
3757
4215
  }
3758
4216
  }
3759
- globalThis.Lightview.$(target).content(node, location);
4217
+ } else if (type === IOP1) {
4218
+ n1 = nstack.pop();
4219
+ f = expr.unaryOps[item.value];
4220
+ nstack.push(f(resolveExpression(n1, values)));
4221
+ } else if (type === IFUNCALL) {
4222
+ argCount = item.value;
4223
+ args = [];
4224
+ while (argCount-- > 0) {
4225
+ args.unshift(resolveExpression(nstack.pop(), values));
4226
+ }
4227
+ f = nstack.pop();
4228
+ if (f.apply && f.call) {
4229
+ nstack.push(f.apply(void 0, args));
4230
+ } else {
4231
+ throw new Error(f + " is not a function");
4232
+ }
4233
+ } else if (type === IFUNDEF) {
4234
+ nstack.push(function() {
4235
+ var n22 = nstack.pop();
4236
+ var args2 = [];
4237
+ var argCount2 = item.value;
4238
+ while (argCount2-- > 0) {
4239
+ args2.unshift(nstack.pop());
4240
+ }
4241
+ var n12 = nstack.pop();
4242
+ var f2 = function() {
4243
+ var scope = Object.assign({}, values);
4244
+ for (var i2 = 0, len2 = args2.length; i2 < len2; i2++) {
4245
+ scope[args2[i2]] = arguments[i2];
4246
+ }
4247
+ return evaluate(n22, expr, scope);
4248
+ };
4249
+ Object.defineProperty(f2, "name", {
4250
+ value: n12,
4251
+ writable: false
4252
+ });
4253
+ values[n12] = f2;
4254
+ return f2;
4255
+ }());
4256
+ } else if (type === IEXPR) {
4257
+ nstack.push(createExpressionEvaluator(item, expr));
4258
+ } else if (type === IEXPREVAL) {
4259
+ nstack.push(item);
4260
+ } else if (type === IMEMBER) {
4261
+ n1 = nstack.pop();
4262
+ nstack.push(n1[item.value]);
4263
+ } else if (type === IENDSTATEMENT) {
4264
+ nstack.pop();
4265
+ } else if (type === IARRAY) {
4266
+ argCount = item.value;
4267
+ args = [];
4268
+ while (argCount-- > 0) {
4269
+ args.unshift(nstack.pop());
4270
+ }
4271
+ nstack.push(args);
4272
+ } else {
4273
+ throw new Error("invalid Expression");
4274
+ }
4275
+ }
4276
+ if (nstack.length > 1) {
4277
+ throw new Error("invalid Expression (parity)");
4278
+ }
4279
+ return nstack[0] === 0 ? 0 : resolveExpression(nstack[0], values);
4280
+ }
4281
+ function createExpressionEvaluator(token, expr, values) {
4282
+ if (isExpressionEvaluator(token)) return token;
4283
+ return {
4284
+ type: IEXPREVAL,
4285
+ value: function(scope) {
4286
+ return evaluate(token.value, expr, scope);
3760
4287
  }
3761
4288
  };
3762
- }, { pathAware: true });
3763
- registerHelper("mount", async (url, options = {}) => {
3764
- const { target = "body", location = "beforeend" } = options;
3765
- try {
3766
- const fetchOptions = { ...options };
3767
- delete fetchOptions.target;
3768
- delete fetchOptions.location;
3769
- const headers = { ...fetchOptions.headers };
3770
- let body = fetchOptions.body;
3771
- if (body !== void 0) {
3772
- if (body !== null && typeof body === "object") {
3773
- body = JSON.stringify(body);
3774
- if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
4289
+ }
4290
+ function isExpressionEvaluator(n) {
4291
+ return n && n.type === IEXPREVAL;
4292
+ }
4293
+ function resolveExpression(n, values) {
4294
+ return isExpressionEvaluator(n) ? n.value(values) : n;
4295
+ }
4296
+ function expressionToString(tokens, toJS) {
4297
+ var nstack = [];
4298
+ var n1, n2, n3;
4299
+ var f, args, argCount;
4300
+ for (var i = 0; i < tokens.length; i++) {
4301
+ var item = tokens[i];
4302
+ var type = item.type;
4303
+ if (type === INUMBER) {
4304
+ if (typeof item.value === "number" && item.value < 0) {
4305
+ nstack.push("(" + item.value + ")");
4306
+ } else if (Array.isArray(item.value)) {
4307
+ nstack.push("[" + item.value.map(escapeValue).join(", ") + "]");
3775
4308
  } else {
3776
- body = String(body);
3777
- if (!headers["Content-Type"]) headers["Content-Type"] = "text/plain";
4309
+ nstack.push(escapeValue(item.value));
3778
4310
  }
3779
- fetchOptions.body = body;
3780
- fetchOptions.headers = headers;
3781
- }
3782
- const response = await globalThis.fetch(url, fetchOptions);
3783
- const contentType = response.headers.get("Content-Type") || "";
3784
- const text = await response.text();
3785
- let content = text;
3786
- const isCDOM = contentType.includes("application/cdom") || contentType.includes("application/jprx") || contentType.includes("application/vdom") || contentType.includes("application/odom") || url.endsWith(".cdom") || url.endsWith(".jprx") || url.endsWith(".vdom") || url.endsWith(".odom");
3787
- if (isCDOM || contentType.includes("application/json") && text.trim().startsWith("{")) {
3788
- try {
3789
- content = hydrate(parseJPRX(text));
3790
- } catch (e) {
4311
+ } else if (type === IOP2) {
4312
+ n2 = nstack.pop();
4313
+ n1 = nstack.pop();
4314
+ f = item.value;
4315
+ if (toJS) {
4316
+ if (f === "^") {
4317
+ nstack.push("Math.pow(" + n1 + ", " + n2 + ")");
4318
+ } else if (f === "and") {
4319
+ nstack.push("(!!" + n1 + " && !!" + n2 + ")");
4320
+ } else if (f === "or") {
4321
+ nstack.push("(!!" + n1 + " || !!" + n2 + ")");
4322
+ } else if (f === "||") {
4323
+ nstack.push("(function(a,b){ return Array.isArray(a) && Array.isArray(b) ? a.concat(b) : String(a) + String(b); }((" + n1 + "),(" + n2 + ")))");
4324
+ } else if (f === "==") {
4325
+ nstack.push("(" + n1 + " === " + n2 + ")");
4326
+ } else if (f === "!=") {
4327
+ nstack.push("(" + n1 + " !== " + n2 + ")");
4328
+ } else if (f === "[") {
4329
+ nstack.push(n1 + "[(" + n2 + ") | 0]");
4330
+ } else {
4331
+ nstack.push("(" + n1 + " " + f + " " + n2 + ")");
4332
+ }
4333
+ } else {
4334
+ if (f === "[") {
4335
+ nstack.push(n1 + "[" + n2 + "]");
4336
+ } else {
4337
+ nstack.push("(" + n1 + " " + f + " " + n2 + ")");
4338
+ }
4339
+ }
4340
+ } else if (type === IOP3) {
4341
+ n3 = nstack.pop();
4342
+ n2 = nstack.pop();
4343
+ n1 = nstack.pop();
4344
+ f = item.value;
4345
+ if (f === "?") {
4346
+ nstack.push("(" + n1 + " ? " + n2 + " : " + n3 + ")");
4347
+ } else {
4348
+ throw new Error("invalid Expression");
4349
+ }
4350
+ } else if (type === IVAR || type === IVARNAME) {
4351
+ nstack.push(item.value);
4352
+ } else if (type === IOP1) {
4353
+ n1 = nstack.pop();
4354
+ f = item.value;
4355
+ if (f === "-" || f === "+") {
4356
+ nstack.push("(" + f + n1 + ")");
4357
+ } else if (toJS) {
4358
+ if (f === "not") {
4359
+ nstack.push("(!" + n1 + ")");
4360
+ } else if (f === "!") {
4361
+ nstack.push("fac(" + n1 + ")");
4362
+ } else {
4363
+ nstack.push(f + "(" + n1 + ")");
4364
+ }
4365
+ } else if (f === "!") {
4366
+ nstack.push("(" + n1 + "!)");
4367
+ } else {
4368
+ nstack.push("(" + f + " " + n1 + ")");
4369
+ }
4370
+ } else if (type === IFUNCALL) {
4371
+ argCount = item.value;
4372
+ args = [];
4373
+ while (argCount-- > 0) {
4374
+ args.unshift(nstack.pop());
4375
+ }
4376
+ f = nstack.pop();
4377
+ nstack.push(f + "(" + args.join(", ") + ")");
4378
+ } else if (type === IFUNDEF) {
4379
+ n2 = nstack.pop();
4380
+ argCount = item.value;
4381
+ args = [];
4382
+ while (argCount-- > 0) {
4383
+ args.unshift(nstack.pop());
4384
+ }
4385
+ n1 = nstack.pop();
4386
+ if (toJS) {
4387
+ nstack.push("(" + n1 + " = function(" + args.join(", ") + ") { return " + n2 + " })");
4388
+ } else {
4389
+ nstack.push("(" + n1 + "(" + args.join(", ") + ") = " + n2 + ")");
3791
4390
  }
4391
+ } else if (type === IMEMBER) {
4392
+ n1 = nstack.pop();
4393
+ nstack.push(n1 + "." + item.value);
4394
+ } else if (type === IARRAY) {
4395
+ argCount = item.value;
4396
+ args = [];
4397
+ while (argCount-- > 0) {
4398
+ args.unshift(nstack.pop());
4399
+ }
4400
+ nstack.push("[" + args.join(", ") + "]");
4401
+ } else if (type === IEXPR) {
4402
+ nstack.push("(" + expressionToString(item.value, toJS) + ")");
4403
+ } else if (type === IENDSTATEMENT) ;
4404
+ else {
4405
+ throw new Error("invalid Expression");
3792
4406
  }
3793
- const targetEl = document.querySelector(target);
3794
- if (targetEl) {
3795
- globalThis.Lightview.$(targetEl).content(content, location);
4407
+ }
4408
+ if (nstack.length > 1) {
4409
+ if (toJS) {
4410
+ nstack = [nstack.join(",")];
3796
4411
  } else {
3797
- console.warn(`[Lightview-CDOM] $mount target not found: ${target}`);
4412
+ nstack = [nstack.join(";")];
3798
4413
  }
3799
- } catch (err) {
3800
- console.error(`[Lightview-CDOM] $mount failed for ${url}:`, err);
3801
4414
  }
3802
- });
3803
- registerOperator("increment", "++", "prefix", 80);
3804
- registerOperator("increment", "++", "postfix", 80);
3805
- registerOperator("decrement", "--", "prefix", 80);
3806
- registerOperator("decrement", "--", "postfix", 80);
3807
- registerOperator("toggle", "!!", "prefix", 80);
3808
- registerOperator("+", "+", "infix", 50);
3809
- registerOperator("-", "-", "infix", 50);
3810
- registerOperator("*", "*", "infix", 60);
3811
- registerOperator("/", "/", "infix", 60);
4415
+ return String(nstack[0]);
4416
+ }
4417
+ function escapeValue(v) {
4418
+ if (typeof v === "string") {
4419
+ return JSON.stringify(v).replace(/\u2028/g, "\\u2028").replace(/\u2029/g, "\\u2029");
4420
+ }
4421
+ return v;
4422
+ }
4423
+ function contains(array, obj) {
4424
+ for (var i = 0; i < array.length; i++) {
4425
+ if (array[i] === obj) {
4426
+ return true;
4427
+ }
4428
+ }
4429
+ return false;
4430
+ }
4431
+ function getSymbols(tokens, symbols, options) {
4432
+ options = options || {};
4433
+ var withMembers = !!options.withMembers;
4434
+ var prevVar = null;
4435
+ for (var i = 0; i < tokens.length; i++) {
4436
+ var item = tokens[i];
4437
+ if (item.type === IVAR || item.type === IVARNAME) {
4438
+ if (!withMembers && !contains(symbols, item.value)) {
4439
+ symbols.push(item.value);
4440
+ } else if (prevVar !== null) {
4441
+ if (!contains(symbols, prevVar)) {
4442
+ symbols.push(prevVar);
4443
+ }
4444
+ prevVar = item.value;
4445
+ } else {
4446
+ prevVar = item.value;
4447
+ }
4448
+ } else if (item.type === IMEMBER && withMembers && prevVar !== null) {
4449
+ prevVar += "." + item.value;
4450
+ } else if (item.type === IEXPR) {
4451
+ getSymbols(item.value, symbols, options);
4452
+ } else if (prevVar !== null) {
4453
+ if (!contains(symbols, prevVar)) {
4454
+ symbols.push(prevVar);
4455
+ }
4456
+ prevVar = null;
4457
+ }
4458
+ }
4459
+ if (prevVar !== null && !contains(symbols, prevVar)) {
4460
+ symbols.push(prevVar);
4461
+ }
4462
+ }
4463
+ function Expression(tokens, parser) {
4464
+ this.tokens = tokens;
4465
+ this.parser = parser;
4466
+ this.unaryOps = parser.unaryOps;
4467
+ this.binaryOps = parser.binaryOps;
4468
+ this.ternaryOps = parser.ternaryOps;
4469
+ this.functions = parser.functions;
4470
+ }
4471
+ Expression.prototype.simplify = function(values) {
4472
+ values = values || {};
4473
+ return new Expression(simplify(this.tokens, this.unaryOps, this.binaryOps, this.ternaryOps, values), this.parser);
4474
+ };
4475
+ Expression.prototype.substitute = function(variable, expr) {
4476
+ if (!(expr instanceof Expression)) {
4477
+ expr = this.parser.parse(String(expr));
4478
+ }
4479
+ return new Expression(substitute(this.tokens, variable, expr), this.parser);
4480
+ };
4481
+ Expression.prototype.evaluate = function(values) {
4482
+ values = values || {};
4483
+ return evaluate(this.tokens, this, values);
4484
+ };
4485
+ Expression.prototype.toString = function() {
4486
+ return expressionToString(this.tokens, false);
4487
+ };
4488
+ Expression.prototype.symbols = function(options) {
4489
+ options = options || {};
4490
+ var vars = [];
4491
+ getSymbols(this.tokens, vars, options);
4492
+ return vars;
4493
+ };
4494
+ Expression.prototype.variables = function(options) {
4495
+ options = options || {};
4496
+ var vars = [];
4497
+ getSymbols(this.tokens, vars, options);
4498
+ var functions = this.functions;
4499
+ return vars.filter(function(name) {
4500
+ return !(name in functions);
4501
+ });
4502
+ };
4503
+ Expression.prototype.toJSFunction = function(param, variables) {
4504
+ var expr = this;
4505
+ var f = new Function(param, "with(this.functions) with (this.ternaryOps) with (this.binaryOps) with (this.unaryOps) { return " + expressionToString(this.simplify(variables).tokens, true) + "; }");
4506
+ return function() {
4507
+ return f.apply(expr, arguments);
4508
+ };
4509
+ };
4510
+ var TEOF = "TEOF";
4511
+ var TOP = "TOP";
4512
+ var TNUMBER = "TNUMBER";
4513
+ var TSTRING = "TSTRING";
4514
+ var TPAREN = "TPAREN";
4515
+ var TBRACKET = "TBRACKET";
4516
+ var TCOMMA = "TCOMMA";
4517
+ var TNAME = "TNAME";
4518
+ var TSEMICOLON = "TSEMICOLON";
4519
+ function Token(type, value, index2) {
4520
+ this.type = type;
4521
+ this.value = value;
4522
+ this.index = index2;
4523
+ }
4524
+ Token.prototype.toString = function() {
4525
+ return this.type + ": " + this.value;
4526
+ };
4527
+ function TokenStream(parser, expression) {
4528
+ this.pos = 0;
4529
+ this.current = null;
4530
+ this.unaryOps = parser.unaryOps;
4531
+ this.binaryOps = parser.binaryOps;
4532
+ this.ternaryOps = parser.ternaryOps;
4533
+ this.consts = parser.consts;
4534
+ this.expression = expression;
4535
+ this.savedPosition = 0;
4536
+ this.savedCurrent = null;
4537
+ this.options = parser.options;
4538
+ this.parser = parser;
4539
+ }
4540
+ TokenStream.prototype.newToken = function(type, value, pos) {
4541
+ return new Token(type, value, pos != null ? pos : this.pos);
4542
+ };
4543
+ TokenStream.prototype.save = function() {
4544
+ this.savedPosition = this.pos;
4545
+ this.savedCurrent = this.current;
4546
+ };
4547
+ TokenStream.prototype.restore = function() {
4548
+ this.pos = this.savedPosition;
4549
+ this.current = this.savedCurrent;
4550
+ };
4551
+ TokenStream.prototype.next = function() {
4552
+ if (this.pos >= this.expression.length) {
4553
+ return this.newToken(TEOF, "EOF");
4554
+ }
4555
+ if (this.isWhitespace() || this.isComment()) {
4556
+ return this.next();
4557
+ } else if (this.isRadixInteger() || this.isNumber() || this.isOperator() || this.isString() || this.isParen() || this.isBracket() || this.isComma() || this.isSemicolon() || this.isNamedOp() || this.isConst() || this.isName()) {
4558
+ return this.current;
4559
+ } else {
4560
+ this.parseError('Unknown character "' + this.expression.charAt(this.pos) + '"');
4561
+ }
4562
+ };
4563
+ TokenStream.prototype.isString = function() {
4564
+ var r = false;
4565
+ var startPos = this.pos;
4566
+ var quote = this.expression.charAt(startPos);
4567
+ if (quote === "'" || quote === '"') {
4568
+ var index2 = this.expression.indexOf(quote, startPos + 1);
4569
+ while (index2 >= 0 && this.pos < this.expression.length) {
4570
+ this.pos = index2 + 1;
4571
+ if (this.expression.charAt(index2 - 1) !== "\\") {
4572
+ var rawString = this.expression.substring(startPos + 1, index2);
4573
+ this.current = this.newToken(TSTRING, this.unescape(rawString), startPos);
4574
+ r = true;
4575
+ break;
4576
+ }
4577
+ index2 = this.expression.indexOf(quote, index2 + 1);
4578
+ }
4579
+ }
4580
+ return r;
4581
+ };
4582
+ TokenStream.prototype.isParen = function() {
4583
+ var c = this.expression.charAt(this.pos);
4584
+ if (c === "(" || c === ")") {
4585
+ this.current = this.newToken(TPAREN, c);
4586
+ this.pos++;
4587
+ return true;
4588
+ }
4589
+ return false;
4590
+ };
4591
+ TokenStream.prototype.isBracket = function() {
4592
+ var c = this.expression.charAt(this.pos);
4593
+ if ((c === "[" || c === "]") && this.isOperatorEnabled("[")) {
4594
+ this.current = this.newToken(TBRACKET, c);
4595
+ this.pos++;
4596
+ return true;
4597
+ }
4598
+ return false;
4599
+ };
4600
+ TokenStream.prototype.isComma = function() {
4601
+ var c = this.expression.charAt(this.pos);
4602
+ if (c === ",") {
4603
+ this.current = this.newToken(TCOMMA, ",");
4604
+ this.pos++;
4605
+ return true;
4606
+ }
4607
+ return false;
4608
+ };
4609
+ TokenStream.prototype.isSemicolon = function() {
4610
+ var c = this.expression.charAt(this.pos);
4611
+ if (c === ";") {
4612
+ this.current = this.newToken(TSEMICOLON, ";");
4613
+ this.pos++;
4614
+ return true;
4615
+ }
4616
+ return false;
4617
+ };
4618
+ TokenStream.prototype.isConst = function() {
4619
+ var startPos = this.pos;
4620
+ var i = startPos;
4621
+ for (; i < this.expression.length; i++) {
4622
+ var c = this.expression.charAt(i);
4623
+ if (c.toUpperCase() === c.toLowerCase()) {
4624
+ if (i === this.pos || c !== "_" && c !== "." && (c < "0" || c > "9")) {
4625
+ break;
4626
+ }
4627
+ }
4628
+ }
4629
+ if (i > startPos) {
4630
+ var str = this.expression.substring(startPos, i);
4631
+ if (str in this.consts) {
4632
+ this.current = this.newToken(TNUMBER, this.consts[str]);
4633
+ this.pos += str.length;
4634
+ return true;
4635
+ }
4636
+ }
4637
+ return false;
4638
+ };
4639
+ TokenStream.prototype.isNamedOp = function() {
4640
+ var startPos = this.pos;
4641
+ var i = startPos;
4642
+ for (; i < this.expression.length; i++) {
4643
+ var c = this.expression.charAt(i);
4644
+ if (c.toUpperCase() === c.toLowerCase()) {
4645
+ if (i === this.pos || c !== "_" && (c < "0" || c > "9")) {
4646
+ break;
4647
+ }
4648
+ }
4649
+ }
4650
+ if (i > startPos) {
4651
+ var str = this.expression.substring(startPos, i);
4652
+ if (this.isOperatorEnabled(str) && (str in this.binaryOps || str in this.unaryOps || str in this.ternaryOps)) {
4653
+ this.current = this.newToken(TOP, str);
4654
+ this.pos += str.length;
4655
+ return true;
4656
+ }
4657
+ }
4658
+ return false;
4659
+ };
4660
+ TokenStream.prototype.isName = function() {
4661
+ var startPos = this.pos;
4662
+ var i = startPos;
4663
+ var hasLetter = false;
4664
+ for (; i < this.expression.length; i++) {
4665
+ var c = this.expression.charAt(i);
4666
+ if (c.toUpperCase() === c.toLowerCase()) {
4667
+ if (i === this.pos && (c === "$" || c === "_")) {
4668
+ if (c === "_") {
4669
+ hasLetter = true;
4670
+ }
4671
+ continue;
4672
+ } else if (i === this.pos || !hasLetter || c !== "_" && (c < "0" || c > "9")) {
4673
+ break;
4674
+ }
4675
+ } else {
4676
+ hasLetter = true;
4677
+ }
4678
+ }
4679
+ if (hasLetter) {
4680
+ var str = this.expression.substring(startPos, i);
4681
+ this.current = this.newToken(TNAME, str);
4682
+ this.pos += str.length;
4683
+ return true;
4684
+ }
4685
+ return false;
4686
+ };
4687
+ TokenStream.prototype.isWhitespace = function() {
4688
+ var r = false;
4689
+ var c = this.expression.charAt(this.pos);
4690
+ while (c === " " || c === " " || c === "\n" || c === "\r") {
4691
+ r = true;
4692
+ this.pos++;
4693
+ if (this.pos >= this.expression.length) {
4694
+ break;
4695
+ }
4696
+ c = this.expression.charAt(this.pos);
4697
+ }
4698
+ return r;
4699
+ };
4700
+ var codePointPattern = /^[0-9a-f]{4}$/i;
4701
+ TokenStream.prototype.unescape = function(v) {
4702
+ var index2 = v.indexOf("\\");
4703
+ if (index2 < 0) {
4704
+ return v;
4705
+ }
4706
+ var buffer = v.substring(0, index2);
4707
+ while (index2 >= 0) {
4708
+ var c = v.charAt(++index2);
4709
+ switch (c) {
4710
+ case "'":
4711
+ buffer += "'";
4712
+ break;
4713
+ case '"':
4714
+ buffer += '"';
4715
+ break;
4716
+ case "\\":
4717
+ buffer += "\\";
4718
+ break;
4719
+ case "/":
4720
+ buffer += "/";
4721
+ break;
4722
+ case "b":
4723
+ buffer += "\b";
4724
+ break;
4725
+ case "f":
4726
+ buffer += "\f";
4727
+ break;
4728
+ case "n":
4729
+ buffer += "\n";
4730
+ break;
4731
+ case "r":
4732
+ buffer += "\r";
4733
+ break;
4734
+ case "t":
4735
+ buffer += " ";
4736
+ break;
4737
+ case "u":
4738
+ var codePoint = v.substring(index2 + 1, index2 + 5);
4739
+ if (!codePointPattern.test(codePoint)) {
4740
+ this.parseError("Illegal escape sequence: \\u" + codePoint);
4741
+ }
4742
+ buffer += String.fromCharCode(parseInt(codePoint, 16));
4743
+ index2 += 4;
4744
+ break;
4745
+ default:
4746
+ throw this.parseError('Illegal escape sequence: "\\' + c + '"');
4747
+ }
4748
+ ++index2;
4749
+ var backslash = v.indexOf("\\", index2);
4750
+ buffer += v.substring(index2, backslash < 0 ? v.length : backslash);
4751
+ index2 = backslash;
4752
+ }
4753
+ return buffer;
4754
+ };
4755
+ TokenStream.prototype.isComment = function() {
4756
+ var c = this.expression.charAt(this.pos);
4757
+ if (c === "/" && this.expression.charAt(this.pos + 1) === "*") {
4758
+ this.pos = this.expression.indexOf("*/", this.pos) + 2;
4759
+ if (this.pos === 1) {
4760
+ this.pos = this.expression.length;
4761
+ }
4762
+ return true;
4763
+ }
4764
+ return false;
4765
+ };
4766
+ TokenStream.prototype.isRadixInteger = function() {
4767
+ var pos = this.pos;
4768
+ if (pos >= this.expression.length - 2 || this.expression.charAt(pos) !== "0") {
4769
+ return false;
4770
+ }
4771
+ ++pos;
4772
+ var radix;
4773
+ var validDigit;
4774
+ if (this.expression.charAt(pos) === "x") {
4775
+ radix = 16;
4776
+ validDigit = /^[0-9a-f]$/i;
4777
+ ++pos;
4778
+ } else if (this.expression.charAt(pos) === "b") {
4779
+ radix = 2;
4780
+ validDigit = /^[01]$/i;
4781
+ ++pos;
4782
+ } else {
4783
+ return false;
4784
+ }
4785
+ var valid = false;
4786
+ var startPos = pos;
4787
+ while (pos < this.expression.length) {
4788
+ var c = this.expression.charAt(pos);
4789
+ if (validDigit.test(c)) {
4790
+ pos++;
4791
+ valid = true;
4792
+ } else {
4793
+ break;
4794
+ }
4795
+ }
4796
+ if (valid) {
4797
+ this.current = this.newToken(TNUMBER, parseInt(this.expression.substring(startPos, pos), radix));
4798
+ this.pos = pos;
4799
+ }
4800
+ return valid;
4801
+ };
4802
+ TokenStream.prototype.isNumber = function() {
4803
+ var valid = false;
4804
+ var pos = this.pos;
4805
+ var startPos = pos;
4806
+ var resetPos = pos;
4807
+ var foundDot = false;
4808
+ var foundDigits = false;
4809
+ var c;
4810
+ while (pos < this.expression.length) {
4811
+ c = this.expression.charAt(pos);
4812
+ if (c >= "0" && c <= "9" || !foundDot && c === ".") {
4813
+ if (c === ".") {
4814
+ foundDot = true;
4815
+ } else {
4816
+ foundDigits = true;
4817
+ }
4818
+ pos++;
4819
+ valid = foundDigits;
4820
+ } else {
4821
+ break;
4822
+ }
4823
+ }
4824
+ if (valid) {
4825
+ resetPos = pos;
4826
+ }
4827
+ if (c === "e" || c === "E") {
4828
+ pos++;
4829
+ var acceptSign = true;
4830
+ var validExponent = false;
4831
+ while (pos < this.expression.length) {
4832
+ c = this.expression.charAt(pos);
4833
+ if (acceptSign && (c === "+" || c === "-")) {
4834
+ acceptSign = false;
4835
+ } else if (c >= "0" && c <= "9") {
4836
+ validExponent = true;
4837
+ acceptSign = false;
4838
+ } else {
4839
+ break;
4840
+ }
4841
+ pos++;
4842
+ }
4843
+ if (!validExponent) {
4844
+ pos = resetPos;
4845
+ }
4846
+ }
4847
+ if (valid) {
4848
+ this.current = this.newToken(TNUMBER, parseFloat(this.expression.substring(startPos, pos)));
4849
+ this.pos = pos;
4850
+ } else {
4851
+ this.pos = resetPos;
4852
+ }
4853
+ return valid;
4854
+ };
4855
+ TokenStream.prototype.isOperator = function() {
4856
+ var startPos = this.pos;
4857
+ var c = this.expression.charAt(this.pos);
4858
+ if (c === "+" || c === "-" || c === "*" || c === "/" || c === "%" || c === "^" || c === "?" || c === ":" || c === ".") {
4859
+ this.current = this.newToken(TOP, c);
4860
+ } else if (c === "∙" || c === "•") {
4861
+ this.current = this.newToken(TOP, "*");
4862
+ } else if (c === ">") {
4863
+ if (this.expression.charAt(this.pos + 1) === "=") {
4864
+ this.current = this.newToken(TOP, ">=");
4865
+ this.pos++;
4866
+ } else {
4867
+ this.current = this.newToken(TOP, ">");
4868
+ }
4869
+ } else if (c === "<") {
4870
+ if (this.expression.charAt(this.pos + 1) === "=") {
4871
+ this.current = this.newToken(TOP, "<=");
4872
+ this.pos++;
4873
+ } else {
4874
+ this.current = this.newToken(TOP, "<");
4875
+ }
4876
+ } else if (c === "|") {
4877
+ if (this.expression.charAt(this.pos + 1) === "|") {
4878
+ this.current = this.newToken(TOP, "||");
4879
+ this.pos++;
4880
+ } else {
4881
+ return false;
4882
+ }
4883
+ } else if (c === "=") {
4884
+ if (this.expression.charAt(this.pos + 1) === "=") {
4885
+ this.current = this.newToken(TOP, "==");
4886
+ this.pos++;
4887
+ } else {
4888
+ this.current = this.newToken(TOP, c);
4889
+ }
4890
+ } else if (c === "!") {
4891
+ if (this.expression.charAt(this.pos + 1) === "=") {
4892
+ this.current = this.newToken(TOP, "!=");
4893
+ this.pos++;
4894
+ } else {
4895
+ this.current = this.newToken(TOP, c);
4896
+ }
4897
+ } else {
4898
+ return false;
4899
+ }
4900
+ this.pos++;
4901
+ if (this.isOperatorEnabled(this.current.value)) {
4902
+ return true;
4903
+ } else {
4904
+ this.pos = startPos;
4905
+ return false;
4906
+ }
4907
+ };
4908
+ TokenStream.prototype.isOperatorEnabled = function(op) {
4909
+ return this.parser.isOperatorEnabled(op);
4910
+ };
4911
+ TokenStream.prototype.getCoordinates = function() {
4912
+ var line = 0;
4913
+ var column;
4914
+ var newline = -1;
4915
+ do {
4916
+ line++;
4917
+ column = this.pos - newline;
4918
+ newline = this.expression.indexOf("\n", newline + 1);
4919
+ } while (newline >= 0 && newline < this.pos);
4920
+ return {
4921
+ line,
4922
+ column
4923
+ };
4924
+ };
4925
+ TokenStream.prototype.parseError = function(msg) {
4926
+ var coords = this.getCoordinates();
4927
+ throw new Error("parse error [" + coords.line + ":" + coords.column + "]: " + msg);
4928
+ };
4929
+ function ParserState(parser, tokenStream, options) {
4930
+ this.parser = parser;
4931
+ this.tokens = tokenStream;
4932
+ this.current = null;
4933
+ this.nextToken = null;
4934
+ this.next();
4935
+ this.savedCurrent = null;
4936
+ this.savedNextToken = null;
4937
+ this.allowMemberAccess = options.allowMemberAccess !== false;
4938
+ }
4939
+ ParserState.prototype.next = function() {
4940
+ this.current = this.nextToken;
4941
+ return this.nextToken = this.tokens.next();
4942
+ };
4943
+ ParserState.prototype.tokenMatches = function(token, value) {
4944
+ if (typeof value === "undefined") {
4945
+ return true;
4946
+ } else if (Array.isArray(value)) {
4947
+ return contains(value, token.value);
4948
+ } else if (typeof value === "function") {
4949
+ return value(token);
4950
+ } else {
4951
+ return token.value === value;
4952
+ }
4953
+ };
4954
+ ParserState.prototype.save = function() {
4955
+ this.savedCurrent = this.current;
4956
+ this.savedNextToken = this.nextToken;
4957
+ this.tokens.save();
4958
+ };
4959
+ ParserState.prototype.restore = function() {
4960
+ this.tokens.restore();
4961
+ this.current = this.savedCurrent;
4962
+ this.nextToken = this.savedNextToken;
4963
+ };
4964
+ ParserState.prototype.accept = function(type, value) {
4965
+ if (this.nextToken.type === type && this.tokenMatches(this.nextToken, value)) {
4966
+ this.next();
4967
+ return true;
4968
+ }
4969
+ return false;
4970
+ };
4971
+ ParserState.prototype.expect = function(type, value) {
4972
+ if (!this.accept(type, value)) {
4973
+ var coords = this.tokens.getCoordinates();
4974
+ throw new Error("parse error [" + coords.line + ":" + coords.column + "]: Expected " + (value || type));
4975
+ }
4976
+ };
4977
+ ParserState.prototype.parseAtom = function(instr) {
4978
+ var unaryOps = this.tokens.unaryOps;
4979
+ function isPrefixOperator(token) {
4980
+ return token.value in unaryOps;
4981
+ }
4982
+ if (this.accept(TNAME) || this.accept(TOP, isPrefixOperator)) {
4983
+ instr.push(new Instruction(IVAR, this.current.value));
4984
+ } else if (this.accept(TNUMBER)) {
4985
+ instr.push(new Instruction(INUMBER, this.current.value));
4986
+ } else if (this.accept(TSTRING)) {
4987
+ instr.push(new Instruction(INUMBER, this.current.value));
4988
+ } else if (this.accept(TPAREN, "(")) {
4989
+ this.parseExpression(instr);
4990
+ this.expect(TPAREN, ")");
4991
+ } else if (this.accept(TBRACKET, "[")) {
4992
+ if (this.accept(TBRACKET, "]")) {
4993
+ instr.push(new Instruction(IARRAY, 0));
4994
+ } else {
4995
+ var argCount = this.parseArrayList(instr);
4996
+ instr.push(new Instruction(IARRAY, argCount));
4997
+ }
4998
+ } else {
4999
+ throw new Error("unexpected " + this.nextToken);
5000
+ }
5001
+ };
5002
+ ParserState.prototype.parseExpression = function(instr) {
5003
+ var exprInstr = [];
5004
+ if (this.parseUntilEndStatement(instr, exprInstr)) {
5005
+ return;
5006
+ }
5007
+ this.parseVariableAssignmentExpression(exprInstr);
5008
+ if (this.parseUntilEndStatement(instr, exprInstr)) {
5009
+ return;
5010
+ }
5011
+ this.pushExpression(instr, exprInstr);
5012
+ };
5013
+ ParserState.prototype.pushExpression = function(instr, exprInstr) {
5014
+ for (var i = 0, len2 = exprInstr.length; i < len2; i++) {
5015
+ instr.push(exprInstr[i]);
5016
+ }
5017
+ };
5018
+ ParserState.prototype.parseUntilEndStatement = function(instr, exprInstr) {
5019
+ if (!this.accept(TSEMICOLON)) return false;
5020
+ if (this.nextToken && this.nextToken.type !== TEOF && !(this.nextToken.type === TPAREN && this.nextToken.value === ")")) {
5021
+ exprInstr.push(new Instruction(IENDSTATEMENT));
5022
+ }
5023
+ if (this.nextToken.type !== TEOF) {
5024
+ this.parseExpression(exprInstr);
5025
+ }
5026
+ instr.push(new Instruction(IEXPR, exprInstr));
5027
+ return true;
5028
+ };
5029
+ ParserState.prototype.parseArrayList = function(instr) {
5030
+ var argCount = 0;
5031
+ while (!this.accept(TBRACKET, "]")) {
5032
+ this.parseExpression(instr);
5033
+ ++argCount;
5034
+ while (this.accept(TCOMMA)) {
5035
+ this.parseExpression(instr);
5036
+ ++argCount;
5037
+ }
5038
+ }
5039
+ return argCount;
5040
+ };
5041
+ ParserState.prototype.parseVariableAssignmentExpression = function(instr) {
5042
+ this.parseConditionalExpression(instr);
5043
+ while (this.accept(TOP, "=")) {
5044
+ var varName = instr.pop();
5045
+ var varValue = [];
5046
+ var lastInstrIndex = instr.length - 1;
5047
+ if (varName.type === IFUNCALL) {
5048
+ if (!this.tokens.isOperatorEnabled("()=")) {
5049
+ throw new Error("function definition is not permitted");
5050
+ }
5051
+ for (var i = 0, len2 = varName.value + 1; i < len2; i++) {
5052
+ var index2 = lastInstrIndex - i;
5053
+ if (instr[index2].type === IVAR) {
5054
+ instr[index2] = new Instruction(IVARNAME, instr[index2].value);
5055
+ }
5056
+ }
5057
+ this.parseVariableAssignmentExpression(varValue);
5058
+ instr.push(new Instruction(IEXPR, varValue));
5059
+ instr.push(new Instruction(IFUNDEF, varName.value));
5060
+ continue;
5061
+ }
5062
+ if (varName.type !== IVAR && varName.type !== IMEMBER) {
5063
+ throw new Error("expected variable for assignment");
5064
+ }
5065
+ this.parseVariableAssignmentExpression(varValue);
5066
+ instr.push(new Instruction(IVARNAME, varName.value));
5067
+ instr.push(new Instruction(IEXPR, varValue));
5068
+ instr.push(binaryInstruction("="));
5069
+ }
5070
+ };
5071
+ ParserState.prototype.parseConditionalExpression = function(instr) {
5072
+ this.parseOrExpression(instr);
5073
+ while (this.accept(TOP, "?")) {
5074
+ var trueBranch = [];
5075
+ var falseBranch = [];
5076
+ this.parseConditionalExpression(trueBranch);
5077
+ this.expect(TOP, ":");
5078
+ this.parseConditionalExpression(falseBranch);
5079
+ instr.push(new Instruction(IEXPR, trueBranch));
5080
+ instr.push(new Instruction(IEXPR, falseBranch));
5081
+ instr.push(ternaryInstruction("?"));
5082
+ }
5083
+ };
5084
+ ParserState.prototype.parseOrExpression = function(instr) {
5085
+ this.parseAndExpression(instr);
5086
+ while (this.accept(TOP, "or")) {
5087
+ var falseBranch = [];
5088
+ this.parseAndExpression(falseBranch);
5089
+ instr.push(new Instruction(IEXPR, falseBranch));
5090
+ instr.push(binaryInstruction("or"));
5091
+ }
5092
+ };
5093
+ ParserState.prototype.parseAndExpression = function(instr) {
5094
+ this.parseComparison(instr);
5095
+ while (this.accept(TOP, "and")) {
5096
+ var trueBranch = [];
5097
+ this.parseComparison(trueBranch);
5098
+ instr.push(new Instruction(IEXPR, trueBranch));
5099
+ instr.push(binaryInstruction("and"));
5100
+ }
5101
+ };
5102
+ var COMPARISON_OPERATORS = ["==", "!=", "<", "<=", ">=", ">", "in"];
5103
+ ParserState.prototype.parseComparison = function(instr) {
5104
+ this.parseAddSub(instr);
5105
+ while (this.accept(TOP, COMPARISON_OPERATORS)) {
5106
+ var op = this.current;
5107
+ this.parseAddSub(instr);
5108
+ instr.push(binaryInstruction(op.value));
5109
+ }
5110
+ };
5111
+ var ADD_SUB_OPERATORS = ["+", "-", "||"];
5112
+ ParserState.prototype.parseAddSub = function(instr) {
5113
+ this.parseTerm(instr);
5114
+ while (this.accept(TOP, ADD_SUB_OPERATORS)) {
5115
+ var op = this.current;
5116
+ this.parseTerm(instr);
5117
+ instr.push(binaryInstruction(op.value));
5118
+ }
5119
+ };
5120
+ var TERM_OPERATORS = ["*", "/", "%"];
5121
+ ParserState.prototype.parseTerm = function(instr) {
5122
+ this.parseFactor(instr);
5123
+ while (this.accept(TOP, TERM_OPERATORS)) {
5124
+ var op = this.current;
5125
+ this.parseFactor(instr);
5126
+ instr.push(binaryInstruction(op.value));
5127
+ }
5128
+ };
5129
+ ParserState.prototype.parseFactor = function(instr) {
5130
+ var unaryOps = this.tokens.unaryOps;
5131
+ function isPrefixOperator(token) {
5132
+ return token.value in unaryOps;
5133
+ }
5134
+ this.save();
5135
+ if (this.accept(TOP, isPrefixOperator)) {
5136
+ if (this.current.value !== "-" && this.current.value !== "+") {
5137
+ if (this.nextToken.type === TPAREN && this.nextToken.value === "(") {
5138
+ this.restore();
5139
+ this.parseExponential(instr);
5140
+ return;
5141
+ } else if (this.nextToken.type === TSEMICOLON || this.nextToken.type === TCOMMA || this.nextToken.type === TEOF || this.nextToken.type === TPAREN && this.nextToken.value === ")") {
5142
+ this.restore();
5143
+ this.parseAtom(instr);
5144
+ return;
5145
+ }
5146
+ }
5147
+ var op = this.current;
5148
+ this.parseFactor(instr);
5149
+ instr.push(unaryInstruction(op.value));
5150
+ } else {
5151
+ this.parseExponential(instr);
5152
+ }
5153
+ };
5154
+ ParserState.prototype.parseExponential = function(instr) {
5155
+ this.parsePostfixExpression(instr);
5156
+ while (this.accept(TOP, "^")) {
5157
+ this.parseFactor(instr);
5158
+ instr.push(binaryInstruction("^"));
5159
+ }
5160
+ };
5161
+ ParserState.prototype.parsePostfixExpression = function(instr) {
5162
+ this.parseFunctionCall(instr);
5163
+ while (this.accept(TOP, "!")) {
5164
+ instr.push(unaryInstruction("!"));
5165
+ }
5166
+ };
5167
+ ParserState.prototype.parseFunctionCall = function(instr) {
5168
+ var unaryOps = this.tokens.unaryOps;
5169
+ function isPrefixOperator(token) {
5170
+ return token.value in unaryOps;
5171
+ }
5172
+ if (this.accept(TOP, isPrefixOperator)) {
5173
+ var op = this.current;
5174
+ this.parseAtom(instr);
5175
+ instr.push(unaryInstruction(op.value));
5176
+ } else {
5177
+ this.parseMemberExpression(instr);
5178
+ while (this.accept(TPAREN, "(")) {
5179
+ if (this.accept(TPAREN, ")")) {
5180
+ instr.push(new Instruction(IFUNCALL, 0));
5181
+ } else {
5182
+ var argCount = this.parseArgumentList(instr);
5183
+ instr.push(new Instruction(IFUNCALL, argCount));
5184
+ }
5185
+ }
5186
+ }
5187
+ };
5188
+ ParserState.prototype.parseArgumentList = function(instr) {
5189
+ var argCount = 0;
5190
+ while (!this.accept(TPAREN, ")")) {
5191
+ this.parseExpression(instr);
5192
+ ++argCount;
5193
+ while (this.accept(TCOMMA)) {
5194
+ this.parseExpression(instr);
5195
+ ++argCount;
5196
+ }
5197
+ }
5198
+ return argCount;
5199
+ };
5200
+ ParserState.prototype.parseMemberExpression = function(instr) {
5201
+ this.parseAtom(instr);
5202
+ while (this.accept(TOP, ".") || this.accept(TBRACKET, "[")) {
5203
+ var op = this.current;
5204
+ if (op.value === ".") {
5205
+ if (!this.allowMemberAccess) {
5206
+ throw new Error('unexpected ".", member access is not permitted');
5207
+ }
5208
+ this.expect(TNAME);
5209
+ instr.push(new Instruction(IMEMBER, this.current.value));
5210
+ } else if (op.value === "[") {
5211
+ if (!this.tokens.isOperatorEnabled("[")) {
5212
+ throw new Error('unexpected "[]", arrays are disabled');
5213
+ }
5214
+ this.parseExpression(instr);
5215
+ this.expect(TBRACKET, "]");
5216
+ instr.push(binaryInstruction("["));
5217
+ } else {
5218
+ throw new Error("unexpected symbol: " + op.value);
5219
+ }
5220
+ }
5221
+ };
5222
+ function add(a, b) {
5223
+ return Number(a) + Number(b);
5224
+ }
5225
+ function sub(a, b) {
5226
+ return a - b;
5227
+ }
5228
+ function mul(a, b) {
5229
+ return a * b;
5230
+ }
5231
+ function div(a, b) {
5232
+ return a / b;
5233
+ }
5234
+ function mod(a, b) {
5235
+ return a % b;
5236
+ }
5237
+ function concat(a, b) {
5238
+ if (Array.isArray(a) && Array.isArray(b)) {
5239
+ return a.concat(b);
5240
+ }
5241
+ return "" + a + b;
5242
+ }
5243
+ function equal(a, b) {
5244
+ return a === b;
5245
+ }
5246
+ function notEqual(a, b) {
5247
+ return a !== b;
5248
+ }
5249
+ function greaterThan(a, b) {
5250
+ return a > b;
5251
+ }
5252
+ function lessThan(a, b) {
5253
+ return a < b;
5254
+ }
5255
+ function greaterThanEqual(a, b) {
5256
+ return a >= b;
5257
+ }
5258
+ function lessThanEqual(a, b) {
5259
+ return a <= b;
5260
+ }
5261
+ function andOperator(a, b) {
5262
+ return Boolean(a && b);
5263
+ }
5264
+ function orOperator(a, b) {
5265
+ return Boolean(a || b);
5266
+ }
5267
+ function inOperator(a, b) {
5268
+ return contains(b, a);
5269
+ }
5270
+ function sinh(a) {
5271
+ return (Math.exp(a) - Math.exp(-a)) / 2;
5272
+ }
5273
+ function cosh(a) {
5274
+ return (Math.exp(a) + Math.exp(-a)) / 2;
5275
+ }
5276
+ function tanh(a) {
5277
+ if (a === Infinity) return 1;
5278
+ if (a === -Infinity) return -1;
5279
+ return (Math.exp(a) - Math.exp(-a)) / (Math.exp(a) + Math.exp(-a));
5280
+ }
5281
+ function asinh(a) {
5282
+ if (a === -Infinity) return a;
5283
+ return Math.log(a + Math.sqrt(a * a + 1));
5284
+ }
5285
+ function acosh(a) {
5286
+ return Math.log(a + Math.sqrt(a * a - 1));
5287
+ }
5288
+ function atanh(a) {
5289
+ return Math.log((1 + a) / (1 - a)) / 2;
5290
+ }
5291
+ function log10(a) {
5292
+ return Math.log(a) * Math.LOG10E;
5293
+ }
5294
+ function neg(a) {
5295
+ return -a;
5296
+ }
5297
+ function not(a) {
5298
+ return !a;
5299
+ }
5300
+ function trunc(a) {
5301
+ return a < 0 ? Math.ceil(a) : Math.floor(a);
5302
+ }
5303
+ function random(a) {
5304
+ return Math.random() * (a || 1);
5305
+ }
5306
+ function factorial(a) {
5307
+ return gamma(a + 1);
5308
+ }
5309
+ function isInteger(value) {
5310
+ return isFinite(value) && value === Math.round(value);
5311
+ }
5312
+ var GAMMA_G = 4.7421875;
5313
+ var GAMMA_P = [
5314
+ 0.9999999999999971,
5315
+ 57.15623566586292,
5316
+ -59.59796035547549,
5317
+ 14.136097974741746,
5318
+ -0.4919138160976202,
5319
+ 3399464998481189e-20,
5320
+ 4652362892704858e-20,
5321
+ -9837447530487956e-20,
5322
+ 1580887032249125e-19,
5323
+ -21026444172410488e-20,
5324
+ 21743961811521265e-20,
5325
+ -1643181065367639e-19,
5326
+ 8441822398385275e-20,
5327
+ -26190838401581408e-21,
5328
+ 36899182659531625e-22
5329
+ ];
5330
+ function gamma(n) {
5331
+ var t, x;
5332
+ if (isInteger(n)) {
5333
+ if (n <= 0) {
5334
+ return isFinite(n) ? Infinity : NaN;
5335
+ }
5336
+ if (n > 171) {
5337
+ return Infinity;
5338
+ }
5339
+ var value = n - 2;
5340
+ var res = n - 1;
5341
+ while (value > 1) {
5342
+ res *= value;
5343
+ value--;
5344
+ }
5345
+ if (res === 0) {
5346
+ res = 1;
5347
+ }
5348
+ return res;
5349
+ }
5350
+ if (n < 0.5) {
5351
+ return Math.PI / (Math.sin(Math.PI * n) * gamma(1 - n));
5352
+ }
5353
+ if (n >= 171.35) {
5354
+ return Infinity;
5355
+ }
5356
+ if (n > 85) {
5357
+ var twoN = n * n;
5358
+ var threeN = twoN * n;
5359
+ var fourN = threeN * n;
5360
+ var fiveN = fourN * n;
5361
+ return Math.sqrt(2 * Math.PI / n) * Math.pow(n / Math.E, n) * (1 + 1 / (12 * n) + 1 / (288 * twoN) - 139 / (51840 * threeN) - 571 / (2488320 * fourN) + 163879 / (209018880 * fiveN) + 5246819 / (75246796800 * fiveN * n));
5362
+ }
5363
+ --n;
5364
+ x = GAMMA_P[0];
5365
+ for (var i = 1; i < GAMMA_P.length; ++i) {
5366
+ x += GAMMA_P[i] / (n + i);
5367
+ }
5368
+ t = n + GAMMA_G + 0.5;
5369
+ return Math.sqrt(2 * Math.PI) * Math.pow(t, n + 0.5) * Math.exp(-t) * x;
5370
+ }
5371
+ function stringOrArrayLength(s) {
5372
+ if (Array.isArray(s)) {
5373
+ return s.length;
5374
+ }
5375
+ return String(s).length;
5376
+ }
5377
+ function hypot() {
5378
+ var sum2 = 0;
5379
+ var larg = 0;
5380
+ for (var i = 0; i < arguments.length; i++) {
5381
+ var arg = Math.abs(arguments[i]);
5382
+ var div2;
5383
+ if (larg < arg) {
5384
+ div2 = larg / arg;
5385
+ sum2 = sum2 * div2 * div2 + 1;
5386
+ larg = arg;
5387
+ } else if (arg > 0) {
5388
+ div2 = arg / larg;
5389
+ sum2 += div2 * div2;
5390
+ } else {
5391
+ sum2 += arg;
5392
+ }
5393
+ }
5394
+ return larg === Infinity ? Infinity : larg * Math.sqrt(sum2);
5395
+ }
5396
+ function condition(cond, yep, nope) {
5397
+ return cond ? yep : nope;
5398
+ }
5399
+ function roundTo(value, exp) {
5400
+ if (typeof exp === "undefined" || +exp === 0) {
5401
+ return Math.round(value);
5402
+ }
5403
+ value = +value;
5404
+ exp = -+exp;
5405
+ if (isNaN(value) || !(typeof exp === "number" && exp % 1 === 0)) {
5406
+ return NaN;
5407
+ }
5408
+ value = value.toString().split("e");
5409
+ value = Math.round(+(value[0] + "e" + (value[1] ? +value[1] - exp : -exp)));
5410
+ value = value.toString().split("e");
5411
+ return +(value[0] + "e" + (value[1] ? +value[1] + exp : exp));
5412
+ }
5413
+ function setVar(name, value, variables) {
5414
+ if (variables) variables[name] = value;
5415
+ return value;
5416
+ }
5417
+ function arrayIndex(array, index2) {
5418
+ return array[index2 | 0];
5419
+ }
5420
+ function max(array) {
5421
+ if (arguments.length === 1 && Array.isArray(array)) {
5422
+ return Math.max.apply(Math, array);
5423
+ } else {
5424
+ return Math.max.apply(Math, arguments);
5425
+ }
5426
+ }
5427
+ function min(array) {
5428
+ if (arguments.length === 1 && Array.isArray(array)) {
5429
+ return Math.min.apply(Math, array);
5430
+ } else {
5431
+ return Math.min.apply(Math, arguments);
5432
+ }
5433
+ }
5434
+ function arrayMap(f, a) {
5435
+ if (typeof f !== "function") {
5436
+ throw new Error("First argument to map is not a function");
5437
+ }
5438
+ if (!Array.isArray(a)) {
5439
+ throw new Error("Second argument to map is not an array");
5440
+ }
5441
+ return a.map(function(x, i) {
5442
+ return f(x, i);
5443
+ });
5444
+ }
5445
+ function arrayFold(f, init, a) {
5446
+ if (typeof f !== "function") {
5447
+ throw new Error("First argument to fold is not a function");
5448
+ }
5449
+ if (!Array.isArray(a)) {
5450
+ throw new Error("Second argument to fold is not an array");
5451
+ }
5452
+ return a.reduce(function(acc, x, i) {
5453
+ return f(acc, x, i);
5454
+ }, init);
5455
+ }
5456
+ function arrayFilter(f, a) {
5457
+ if (typeof f !== "function") {
5458
+ throw new Error("First argument to filter is not a function");
5459
+ }
5460
+ if (!Array.isArray(a)) {
5461
+ throw new Error("Second argument to filter is not an array");
5462
+ }
5463
+ return a.filter(function(x, i) {
5464
+ return f(x, i);
5465
+ });
5466
+ }
5467
+ function stringOrArrayIndexOf(target, s) {
5468
+ if (!(Array.isArray(s) || typeof s === "string")) {
5469
+ throw new Error("Second argument to indexOf is not a string or array");
5470
+ }
5471
+ return s.indexOf(target);
5472
+ }
5473
+ function arrayJoin(sep, a) {
5474
+ if (!Array.isArray(a)) {
5475
+ throw new Error("Second argument to join is not an array");
5476
+ }
5477
+ return a.join(sep);
5478
+ }
5479
+ function sign(x) {
5480
+ return (x > 0) - (x < 0) || +x;
5481
+ }
5482
+ var ONE_THIRD = 1 / 3;
5483
+ function cbrt(x) {
5484
+ return x < 0 ? -Math.pow(-x, ONE_THIRD) : Math.pow(x, ONE_THIRD);
5485
+ }
5486
+ function expm1(x) {
5487
+ return Math.exp(x) - 1;
5488
+ }
5489
+ function log1p(x) {
5490
+ return Math.log(1 + x);
5491
+ }
5492
+ function log2(x) {
5493
+ return Math.log(x) / Math.LN2;
5494
+ }
5495
+ function Parser(options) {
5496
+ this.options = options || {};
5497
+ this.unaryOps = {
5498
+ sin: Math.sin,
5499
+ cos: Math.cos,
5500
+ tan: Math.tan,
5501
+ asin: Math.asin,
5502
+ acos: Math.acos,
5503
+ atan: Math.atan,
5504
+ sinh: Math.sinh || sinh,
5505
+ cosh: Math.cosh || cosh,
5506
+ tanh: Math.tanh || tanh,
5507
+ asinh: Math.asinh || asinh,
5508
+ acosh: Math.acosh || acosh,
5509
+ atanh: Math.atanh || atanh,
5510
+ sqrt: Math.sqrt,
5511
+ cbrt: Math.cbrt || cbrt,
5512
+ log: Math.log,
5513
+ log2: Math.log2 || log2,
5514
+ ln: Math.log,
5515
+ lg: Math.log10 || log10,
5516
+ log10: Math.log10 || log10,
5517
+ expm1: Math.expm1 || expm1,
5518
+ log1p: Math.log1p || log1p,
5519
+ abs: Math.abs,
5520
+ ceil: Math.ceil,
5521
+ floor: Math.floor,
5522
+ round: Math.round,
5523
+ trunc: Math.trunc || trunc,
5524
+ "-": neg,
5525
+ "+": Number,
5526
+ exp: Math.exp,
5527
+ not,
5528
+ length: stringOrArrayLength,
5529
+ "!": factorial,
5530
+ sign: Math.sign || sign
5531
+ };
5532
+ this.binaryOps = {
5533
+ "+": add,
5534
+ "-": sub,
5535
+ "*": mul,
5536
+ "/": div,
5537
+ "%": mod,
5538
+ "^": Math.pow,
5539
+ "||": concat,
5540
+ "==": equal,
5541
+ "!=": notEqual,
5542
+ ">": greaterThan,
5543
+ "<": lessThan,
5544
+ ">=": greaterThanEqual,
5545
+ "<=": lessThanEqual,
5546
+ and: andOperator,
5547
+ or: orOperator,
5548
+ "in": inOperator,
5549
+ "=": setVar,
5550
+ "[": arrayIndex
5551
+ };
5552
+ this.ternaryOps = {
5553
+ "?": condition
5554
+ };
5555
+ this.functions = {
5556
+ random,
5557
+ fac: factorial,
5558
+ min,
5559
+ max,
5560
+ hypot: Math.hypot || hypot,
5561
+ pyt: Math.hypot || hypot,
5562
+ // backward compat
5563
+ pow: Math.pow,
5564
+ atan2: Math.atan2,
5565
+ "if": condition,
5566
+ gamma,
5567
+ roundTo,
5568
+ map: arrayMap,
5569
+ fold: arrayFold,
5570
+ filter: arrayFilter,
5571
+ indexOf: stringOrArrayIndexOf,
5572
+ join: arrayJoin
5573
+ };
5574
+ this.consts = {
5575
+ E: Math.E,
5576
+ PI: Math.PI,
5577
+ "true": true,
5578
+ "false": false
5579
+ };
5580
+ }
5581
+ Parser.prototype.parse = function(expr) {
5582
+ var instr = [];
5583
+ var parserState = new ParserState(
5584
+ this,
5585
+ new TokenStream(this, expr),
5586
+ { allowMemberAccess: this.options.allowMemberAccess }
5587
+ );
5588
+ parserState.parseExpression(instr);
5589
+ parserState.expect(TEOF, "EOF");
5590
+ return new Expression(instr, this);
5591
+ };
5592
+ Parser.prototype.evaluate = function(expr, variables) {
5593
+ return this.parse(expr).evaluate(variables);
5594
+ };
5595
+ var sharedParser = new Parser();
5596
+ Parser.parse = function(expr) {
5597
+ return sharedParser.parse(expr);
5598
+ };
5599
+ Parser.evaluate = function(expr, variables) {
5600
+ return sharedParser.parse(expr).evaluate(variables);
5601
+ };
5602
+ var optionNameMap = {
5603
+ "+": "add",
5604
+ "-": "subtract",
5605
+ "*": "multiply",
5606
+ "/": "divide",
5607
+ "%": "remainder",
5608
+ "^": "power",
5609
+ "!": "factorial",
5610
+ "<": "comparison",
5611
+ ">": "comparison",
5612
+ "<=": "comparison",
5613
+ ">=": "comparison",
5614
+ "==": "comparison",
5615
+ "!=": "comparison",
5616
+ "||": "concatenate",
5617
+ "and": "logical",
5618
+ "or": "logical",
5619
+ "not": "logical",
5620
+ "?": "conditional",
5621
+ ":": "conditional",
5622
+ "=": "assignment",
5623
+ "[": "array",
5624
+ "()=": "fndef"
5625
+ };
5626
+ function getOptionName(op) {
5627
+ return optionNameMap.hasOwnProperty(op) ? optionNameMap[op] : op;
5628
+ }
5629
+ Parser.prototype.isOperatorEnabled = function(op) {
5630
+ var optionName = getOptionName(op);
5631
+ var operators2 = this.options.operators || {};
5632
+ return !(optionName in operators2) || !!operators2[optionName];
5633
+ };
5634
+ const calc = (expression, context) => {
5635
+ if (typeof expression !== "string") {
5636
+ return expression;
5637
+ }
5638
+ let processedExpression = expression;
5639
+ try {
5640
+ const pathResolver = (path) => {
5641
+ let currentPath = path;
5642
+ let value;
5643
+ let depth = 0;
5644
+ while (typeof currentPath === "string" && (currentPath.startsWith("/") || currentPath.startsWith("=/")) && depth < 5) {
5645
+ const normalizedPath = currentPath.startsWith("/") ? "=" + currentPath : currentPath;
5646
+ const resolved = resolvePath(normalizedPath, context);
5647
+ value = unwrapSignal(resolved);
5648
+ if (typeof value === "string" && (value.startsWith("/") || value.startsWith("=/")) && value !== currentPath) {
5649
+ currentPath = value;
5650
+ depth++;
5651
+ } else {
5652
+ break;
5653
+ }
5654
+ }
5655
+ if (typeof value === "number") return value;
5656
+ if (typeof value === "string") {
5657
+ const num = parseFloat(value);
5658
+ if (!isNaN(num) && isFinite(Number(value))) return num;
5659
+ return value === "" ? 0 : `"${value.replace(/"/g, '\\"')}"`;
5660
+ }
5661
+ return value === void 0 || value === null ? 0 : value;
5662
+ };
5663
+ const pathRegex = /\$\(\s*['"](.*?)['"]\s*\)/g;
5664
+ processedExpression = expression.replace(pathRegex, (match2, path) => {
5665
+ const val = pathResolver(path);
5666
+ return val;
5667
+ });
5668
+ const parser = new Parser();
5669
+ const parsed = parser.parse(processedExpression);
5670
+ return parsed.evaluate();
5671
+ } catch (error) {
5672
+ console.error("JPRX calc error:", error.message);
5673
+ console.error("Original expression:", expression);
5674
+ console.error("Processed expression:", processedExpression);
5675
+ return NaN;
5676
+ }
5677
+ };
5678
+ const registerCalcHelpers = (register) => {
5679
+ register("calc", calc, { pathAware: true });
5680
+ };
5681
+ const registerDOMHelpers = (registerHelper2) => {
5682
+ registerHelper2("xpath", function(expression) {
5683
+ const domNode = this;
5684
+ if (!domNode || !(domNode instanceof Element)) {
5685
+ console.warn("[Lightview-CDOM] xpath() called without valid DOM context");
5686
+ return "";
5687
+ }
5688
+ const forbiddenAxes = /\b(child|descendant|following|following-sibling)::/;
5689
+ if (forbiddenAxes.test(expression)) {
5690
+ console.error(`[Lightview-CDOM] xpath(): Forward-looking axes not allowed: ${expression}`);
5691
+ return "";
5692
+ }
5693
+ const hasShorthandChild = /\/[a-zA-Z]/.test(expression) && !expression.startsWith("/html");
5694
+ if (hasShorthandChild) {
5695
+ console.error(`[Lightview-CDOM] xpath(): Shorthand child axis (/) not allowed: ${expression}`);
5696
+ return "";
5697
+ }
5698
+ const LV = globalThis.Lightview;
5699
+ if (!LV || !LV.computed) {
5700
+ console.warn("[Lightview-CDOM] xpath(): Lightview not available");
5701
+ return "";
5702
+ }
5703
+ return LV.computed(() => {
5704
+ try {
5705
+ const result = document.evaluate(
5706
+ expression,
5707
+ domNode,
5708
+ null,
5709
+ XPathResult.STRING_TYPE,
5710
+ null
5711
+ );
5712
+ return result.stringValue;
5713
+ } catch (e) {
5714
+ console.error(`[Lightview-CDOM] xpath() evaluation failed:`, e.message);
5715
+ return "";
5716
+ }
5717
+ });
5718
+ }, { pathAware: false });
5719
+ };
5720
+ registerMathHelpers(registerHelper);
5721
+ registerLogicHelpers(registerHelper);
5722
+ registerStringHelpers(registerHelper);
5723
+ registerArrayHelpers(registerHelper);
5724
+ registerCompareHelpers(registerHelper);
5725
+ registerConditionalHelpers(registerHelper);
5726
+ registerDateTimeHelpers(registerHelper);
5727
+ registerFormatHelpers(registerHelper);
5728
+ registerLookupHelpers(registerHelper);
5729
+ registerStatsHelpers(registerHelper);
5730
+ registerStateHelpers((name, fn) => registerHelper(name, fn, { pathAware: true }));
5731
+ registerNetworkHelpers(registerHelper);
5732
+ registerCalcHelpers(registerHelper);
5733
+ registerDOMHelpers(registerHelper);
5734
+ registerHelper("move", (selector, location = "beforeend") => {
5735
+ return {
5736
+ isLazy: true,
5737
+ resolve: (eventOrNode) => {
5738
+ const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
5739
+ const node = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
5740
+ if (!(node instanceof Node) || !selector) return;
5741
+ const target = document.querySelector(selector);
5742
+ if (!target) {
5743
+ console.warn(`[Lightview-CDOM] move target not found: ${selector}`);
5744
+ return;
5745
+ }
5746
+ if (node.id) {
5747
+ const escapedId = CSS.escape(node.id);
5748
+ if (target.id === node.id && target !== node) {
5749
+ target.replaceWith(node);
5750
+ return;
5751
+ }
5752
+ const existing = target.querySelector(`#${escapedId}`);
5753
+ if (existing && existing !== node) {
5754
+ existing.replaceWith(node);
5755
+ return;
5756
+ }
5757
+ }
5758
+ globalThis.Lightview.$(target).content(node, location);
5759
+ }
5760
+ };
5761
+ }, { pathAware: true });
5762
+ registerHelper("mount", async (url, options = {}) => {
5763
+ const { target = "body", location = "beforeend" } = options;
5764
+ try {
5765
+ const fetchOptions = { ...options };
5766
+ delete fetchOptions.target;
5767
+ delete fetchOptions.location;
5768
+ const headers = { ...fetchOptions.headers };
5769
+ let body = fetchOptions.body;
5770
+ if (body !== void 0) {
5771
+ if (body !== null && typeof body === "object") {
5772
+ body = JSON.stringify(body);
5773
+ if (!headers["Content-Type"]) headers["Content-Type"] = "application/json";
5774
+ } else {
5775
+ body = String(body);
5776
+ if (!headers["Content-Type"]) headers["Content-Type"] = "text/plain";
5777
+ }
5778
+ fetchOptions.body = body;
5779
+ fetchOptions.headers = headers;
5780
+ }
5781
+ const response = await globalThis.fetch(url, fetchOptions);
5782
+ const contentType = response.headers.get("Content-Type") || "";
5783
+ const text = await response.text();
5784
+ let content = text;
5785
+ const isCDOM = contentType.includes("application/cdom") || contentType.includes("application/jprx") || contentType.includes("application/vdom") || contentType.includes("application/odom") || url.endsWith(".cdom") || url.endsWith(".jprx") || url.endsWith(".vdom") || url.endsWith(".odom");
5786
+ if (isCDOM || contentType.includes("application/json") && text.trim().startsWith("{")) {
5787
+ try {
5788
+ content = hydrate(parseJPRX(text));
5789
+ } catch (e) {
5790
+ }
5791
+ }
5792
+ const targetEl = document.querySelector(target);
5793
+ if (targetEl) {
5794
+ globalThis.Lightview.$(targetEl).content(content, location);
5795
+ } else {
5796
+ console.warn(`[Lightview-CDOM] $mount target not found: ${target}`);
5797
+ }
5798
+ } catch (err) {
5799
+ console.error(`[Lightview-CDOM] $mount failed for ${url}:`, err);
5800
+ }
5801
+ });
5802
+ registerOperator("increment", "++", "prefix", 80);
5803
+ registerOperator("increment", "++", "postfix", 80);
5804
+ registerOperator("decrement", "--", "prefix", 80);
5805
+ registerOperator("decrement", "--", "postfix", 80);
5806
+ registerOperator("toggle", "!!", "prefix", 80);
5807
+ registerOperator("set", "=", "infix", 20);
5808
+ registerOperator("+", "+", "infix", 50);
5809
+ registerOperator("-", "-", "infix", 50, { requiresWhitespace: true });
5810
+ registerOperator("*", "*", "infix", 60, { requiresWhitespace: true });
5811
+ registerOperator("/", "/", "infix", 60, { requiresWhitespace: true });
3812
5812
  registerOperator("gt", ">", "infix", 40);
3813
5813
  registerOperator("lt", "<", "infix", 40);
3814
5814
  registerOperator("gte", ">=", "infix", 40);
3815
5815
  registerOperator("lte", "<=", "infix", 40);
3816
5816
  registerOperator("neq", "!=", "infix", 40);
5817
+ registerOperator("strictNeq", "!==", "infix", 40);
5818
+ registerOperator("eq", "==", "infix", 40);
5819
+ registerOperator("strictEq", "===", "infix", 40);
3817
5820
  const getContext = (node, event = null) => {
3818
5821
  return new Proxy({}, {
3819
5822
  get(_, prop) {
@@ -3865,8 +5868,8 @@
3865
5868
  const isEvent = eventOrNode && typeof eventOrNode === "object" && "target" in eventOrNode;
3866
5869
  const target = isEvent ? eventOrNode.currentTarget || eventOrNode.target : eventOrNode;
3867
5870
  const context = getContext(target, isEvent ? eventOrNode : null);
3868
- const result = resolveExpression(expr, context);
3869
- if (result && typeof result === "object" && result.isLazy) return result.resolve(eventOrNode);
5871
+ const result = resolveExpression$1(expr, context);
5872
+ if (result && typeof result === "object" && result.isLazy) return result.resolve(context);
3870
5873
  return result;
3871
5874
  };
3872
5875
  const hydrate = (node, parent = null) => {
@@ -3875,6 +5878,12 @@
3875
5878
  if (typeof node === "string" && node.startsWith("'=")) {
3876
5879
  return node.slice(1);
3877
5880
  }
5881
+ if (typeof node === "string" && node.startsWith("'#")) {
5882
+ return node.slice(1);
5883
+ }
5884
+ if (typeof node === "string" && node.startsWith("#")) {
5885
+ return { __xpath__: node.slice(1), __static__: true };
5886
+ }
3878
5887
  if (typeof node === "string" && node.startsWith("=")) {
3879
5888
  return parseExpression(node, parent);
3880
5889
  }
@@ -3918,6 +5927,10 @@
3918
5927
  const attrVal = value[attrKey];
3919
5928
  if (typeof attrVal === "string" && attrVal.startsWith("'=")) {
3920
5929
  value[attrKey] = attrVal.slice(1);
5930
+ } else if (typeof attrVal === "string" && attrVal.startsWith("'#")) {
5931
+ value[attrKey] = attrVal.slice(1);
5932
+ } else if (typeof attrVal === "string" && attrVal.startsWith("#")) {
5933
+ value[attrKey] = { __xpath__: attrVal.slice(1), __static__: true };
3921
5934
  } else if (typeof attrVal === "string" && attrVal.startsWith("=")) {
3922
5935
  if (attrKey.startsWith("on")) {
3923
5936
  value[attrKey] = makeEventHandler(attrVal);
@@ -3932,6 +5945,10 @@
3932
5945
  }
3933
5946
  if (typeof value === "string" && value.startsWith("'=")) {
3934
5947
  node[key] = value.slice(1);
5948
+ } else if (typeof value === "string" && value.startsWith("'#")) {
5949
+ node[key] = value.slice(1);
5950
+ } else if (typeof value === "string" && value.startsWith("#")) {
5951
+ node[key] = { __xpath__: value.slice(1), __static__: true };
3935
5952
  } else if (typeof value === "string" && value.startsWith("=")) {
3936
5953
  if (key === "onmount" || key === "onunmount" || key.startsWith("on")) {
3937
5954
  node[key] = makeEventHandler(value);
@@ -3946,13 +5963,82 @@
3946
5963
  }
3947
5964
  return node;
3948
5965
  };
5966
+ const validateXPath = (xpath) => {
5967
+ const forbiddenAxes = /\b(child|descendant|following|following-sibling)::/;
5968
+ if (forbiddenAxes.test(xpath)) {
5969
+ throw new Error(`XPath: Forward-looking axes not allowed during DOM construction: ${xpath}`);
5970
+ }
5971
+ const hasShorthandChild = /\/[a-zA-Z]/.test(xpath) && !xpath.startsWith("/html");
5972
+ if (hasShorthandChild) {
5973
+ throw new Error(`XPath: Shorthand child axis (/) not allowed during DOM construction: ${xpath}`);
5974
+ }
5975
+ };
5976
+ const resolveStaticXPath = (rootNode) => {
5977
+ var _a2, _b2;
5978
+ if (!rootNode || !rootNode.nodeType) return;
5979
+ const walker = document.createTreeWalker(
5980
+ rootNode,
5981
+ NodeFilter.SHOW_ALL
5982
+ );
5983
+ const nodesToProcess = [];
5984
+ let node = walker.nextNode();
5985
+ while (node) {
5986
+ nodesToProcess.push(node);
5987
+ node = walker.nextNode();
5988
+ }
5989
+ for (const node2 of nodesToProcess) {
5990
+ if (node2.nodeType === Node.ELEMENT_NODE) {
5991
+ const attributes = [...node2.attributes];
5992
+ for (const attr of attributes) {
5993
+ if (attr.name.startsWith("data-xpath-")) {
5994
+ const realAttr = attr.name.replace("data-xpath-", "");
5995
+ const xpath = attr.value;
5996
+ try {
5997
+ validateXPath(xpath);
5998
+ const result = document.evaluate(
5999
+ xpath,
6000
+ node2,
6001
+ null,
6002
+ XPathResult.STRING_TYPE,
6003
+ null
6004
+ );
6005
+ node2.setAttribute(realAttr, result.stringValue);
6006
+ node2.removeAttribute(attr.name);
6007
+ } catch (e) {
6008
+ (_a2 = globalThis.console) == null ? void 0 : _a2.error(`[Lightview-CDOM] XPath resolution failed for attribute "${realAttr}":`, e.message);
6009
+ }
6010
+ }
6011
+ }
6012
+ }
6013
+ if (node2.__xpathExpr) {
6014
+ const xpath = node2.__xpathExpr;
6015
+ try {
6016
+ validateXPath(xpath);
6017
+ const result = document.evaluate(
6018
+ xpath,
6019
+ node2,
6020
+ // Use text node as context, not its parent!
6021
+ null,
6022
+ XPathResult.STRING_TYPE,
6023
+ null
6024
+ );
6025
+ node2.textContent = result.stringValue;
6026
+ delete node2.__xpathExpr;
6027
+ } catch (e) {
6028
+ (_b2 = globalThis.console) == null ? void 0 : _b2.error(`[Lightview-CDOM] XPath resolution failed for text node:`, e.message);
6029
+ }
6030
+ }
6031
+ }
6032
+ };
6033
+ if (typeof parseCDOMC !== "function") throw new Error("parseCDOMC not found");
6034
+ if (typeof parseJPRX !== "function") throw new Error("parseJPRX not found");
3949
6035
  const LightviewCDOM = {
3950
6036
  registerHelper,
3951
6037
  registerOperator,
3952
6038
  parseExpression,
3953
6039
  resolvePath,
3954
6040
  resolvePathAsContext,
3955
- resolveExpression,
6041
+ resolveExpression: resolveExpression$1,
3956
6042
  parseCDOMC,
3957
6043
  parseJPRX,
3958
6044
  unwrapSignal,
@@ -3963,10 +6049,12 @@
3963
6049
  },
3964
6050
  activate,
3965
6051
  hydrate,
6052
+ resolveStaticXPath,
3966
6053
  version: "1.0.0"
3967
6054
  };
3968
6055
  if (typeof window !== "undefined") {
3969
- globalThis.LightviewCDOM = LightviewCDOM;
6056
+ globalThis.LightviewCDOM = {};
6057
+ Object.assign(globalThis.LightviewCDOM, LightviewCDOM);
3970
6058
  }
3971
6059
  console.log("Lightview Full Bundle Loaded");
3972
6060
  })();