@hyperfixi/core 2.3.0 → 2.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (203) hide show
  1. package/README.md +8 -11
  2. package/dist/api/dom-processor.d.ts +8 -4
  3. package/dist/api/hyperscript-api.d.ts +5 -1
  4. package/dist/ast-utils/index.js +25320 -94
  5. package/dist/ast-utils/index.mjs +25320 -94
  6. package/dist/ast-utils/interchange/types.d.ts +7 -1
  7. package/dist/behaviors/index.js +54 -100
  8. package/dist/behaviors/index.mjs +54 -100
  9. package/dist/bundle-generator/index.js +44 -6
  10. package/dist/bundle-generator/index.mjs +44 -6
  11. package/dist/bundle-generator/parser-templates.d.ts +1 -1
  12. package/dist/bundle-generator/template-capabilities.d.ts +1 -1
  13. package/dist/chunks/bridge-C4d3blZX.js +2 -0
  14. package/dist/chunks/browser-modular-BwIRlrTM.js +2 -0
  15. package/dist/chunks/feature-eventsource-BpZvPy_K.js +2 -0
  16. package/dist/chunks/{feature-sockets-ClOH7vk7.js → feature-sockets-CrYvjZ4j.js} +2 -2
  17. package/dist/chunks/feature-webworker-BSYguEIW.js +2 -0
  18. package/dist/chunks/index-Beno_SBy.js +2 -0
  19. package/dist/commands/advanced/async.d.ts +6 -2
  20. package/dist/commands/advanced/js.d.ts +1 -1
  21. package/dist/commands/animation/start-view-transition.d.ts +24 -0
  22. package/dist/commands/async/fetch.d.ts +6 -1
  23. package/dist/commands/control-flow/repeat.d.ts +2 -0
  24. package/dist/commands/data/clear.d.ts +23 -0
  25. package/dist/commands/data/set.d.ts +6 -0
  26. package/dist/commands/dom/close.d.ts +19 -0
  27. package/dist/commands/dom/empty.d.ts +19 -0
  28. package/dist/commands/dom/open.d.ts +21 -0
  29. package/dist/commands/dom/reset.d.ts +19 -0
  30. package/dist/commands/dom/select.d.ts +19 -0
  31. package/dist/commands/dom/swap.d.ts +7 -4
  32. package/dist/commands/events/trigger.d.ts +1 -1
  33. package/dist/commands/execution/blur.d.ts +19 -0
  34. package/dist/commands/execution/call.d.ts +1 -2
  35. package/dist/commands/execution/focus.d.ts +19 -0
  36. package/dist/commands/helpers/element-resolution.d.ts +2 -2
  37. package/dist/commands/helpers/event-waiting.d.ts +1 -1
  38. package/dist/commands/helpers/numeric-target-parser.d.ts +7 -0
  39. package/dist/commands/index.d.ts +34 -2
  40. package/dist/commands/index.js +19374 -4848
  41. package/dist/commands/index.mjs +19342 -4849
  42. package/dist/commands/navigation/go.d.ts +3 -0
  43. package/dist/commands/navigation/scroll-to.d.ts +26 -0
  44. package/dist/commands/utility/beep.d.ts +2 -2
  45. package/dist/commands/utility/breakpoint.d.ts +19 -0
  46. package/dist/commands/utility/pick.d.ts +11 -2
  47. package/dist/compatibility/browser-bundle-modular.d.ts +2 -2
  48. package/dist/compatibility/browser-bundle-multilingual.d.ts +1 -1
  49. package/dist/compatibility/browser-bundle-semantic-complete.d.ts +3 -3
  50. package/dist/compatibility/browser-bundle.d.ts +13 -6
  51. package/dist/compatibility/browser-modular.d.ts +1 -3
  52. package/dist/core/expression-evaluator.d.ts +4 -4
  53. package/dist/core/expression-registry.d.ts +8 -0
  54. package/dist/expressions/bundles/common-expressions.d.ts +2 -2
  55. package/dist/expressions/bundles/core-expressions.d.ts +2 -2
  56. package/dist/expressions/bundles/full-expressions.d.ts +2 -2
  57. package/dist/expressions/bundles/index.d.ts +3 -3
  58. package/dist/expressions/collection/index.d.ts +35 -0
  59. package/dist/expressions/conversion/impl/index.d.ts +1 -1
  60. package/dist/expressions/index.d.ts +4 -3
  61. package/dist/expressions/index.js +1117 -1590
  62. package/dist/expressions/index.mjs +1113 -1586
  63. package/dist/expressions/logical/index.d.ts +2 -0
  64. package/dist/expressions/mathematical/index.d.ts +11 -0
  65. package/dist/expressions/shared/index.d.ts +1 -1
  66. package/dist/expressions/shared/number-utils.d.ts +1 -0
  67. package/dist/htmx/htmx-attribute-processor.d.ts +37 -1
  68. package/dist/htmx/htmx-translator.d.ts +2 -0
  69. package/dist/htmx/i18n-hooks.d.ts +15 -0
  70. package/dist/htmx/i18n-orchestrator.d.ts +15 -0
  71. package/dist/htmx/lang-resolver.d.ts +3 -0
  72. package/dist/htmx/sse.d.ts +60 -0
  73. package/dist/htmx/ws.d.ts +59 -0
  74. package/dist/hyperfixi-browser-classic-i18n.js +2 -0
  75. package/dist/hyperfixi-browser-minimal.js +1 -0
  76. package/dist/hyperfixi-browser-standard.js +2 -0
  77. package/dist/hyperfixi-browser.js +2 -0
  78. package/dist/hyperfixi-classic-i18n.js +1 -1
  79. package/dist/hyperfixi-hx-v4.js +1 -0
  80. package/dist/hyperfixi-hx.js +1 -1
  81. package/dist/hyperfixi-hybrid-complete.js +1 -1
  82. package/dist/hyperfixi-hybrid-hx.js +1 -0
  83. package/dist/hyperfixi-minimal.js +1 -1
  84. package/dist/hyperfixi-multilingual.js +1 -1
  85. package/dist/hyperfixi-standard.js +1 -1
  86. package/dist/hyperfixi.js +1 -1
  87. package/dist/hyperfixi.mjs +1 -1
  88. package/dist/index.d.ts +2 -0
  89. package/dist/index.js +43613 -45063
  90. package/dist/index.min.js +1 -1
  91. package/dist/index.mjs +43610 -45064
  92. package/dist/lib/index.d.ts +2 -2
  93. package/dist/lib/morph-adapter.d.ts +0 -13
  94. package/dist/lib/swap-executor.d.ts +0 -10
  95. package/dist/lib/view-transitions.d.ts +1 -30
  96. package/dist/lokascript-browser-classic-i18n.js +1 -1
  97. package/dist/lokascript-browser-minimal.js +1 -1
  98. package/dist/lokascript-browser-standard.js +1 -1
  99. package/dist/lokascript-browser.js +1 -1
  100. package/dist/lokascript-hybrid-complete.js +1 -1
  101. package/dist/lokascript-hybrid-hx.js +1 -1
  102. package/dist/lokascript-multilingual.js +1 -1
  103. package/dist/lsp-metadata.d.ts +9 -4
  104. package/dist/lsp-metadata.js +187 -3
  105. package/dist/lsp-metadata.mjs +185 -4
  106. package/dist/metadata.d.ts +1 -1
  107. package/dist/metadata.js +3 -3
  108. package/dist/metadata.mjs +3 -3
  109. package/dist/multilingual/bridge.d.ts +1 -1
  110. package/dist/multilingual/index.js +79 -22
  111. package/dist/multilingual/index.mjs +79 -22
  112. package/dist/parser/command-parsers/animation-commands.d.ts +1 -0
  113. package/dist/parser/command-parsers/utility-commands.d.ts +1 -0
  114. package/dist/parser/extensions.d.ts +51 -0
  115. package/dist/parser/full-parser.js +1224 -899
  116. package/dist/parser/full-parser.mjs +1224 -899
  117. package/dist/parser/helpers/ast-helpers.d.ts +1 -0
  118. package/dist/parser/helpers/parsing-helpers.d.ts +4 -0
  119. package/dist/parser/hybrid/index.js +7 -0
  120. package/dist/parser/hybrid/index.mjs +7 -0
  121. package/dist/parser/hybrid/parser-core.js +7 -0
  122. package/dist/parser/hybrid/parser-core.mjs +7 -0
  123. package/dist/parser/hybrid/tokenizer.js +7 -0
  124. package/dist/parser/hybrid/tokenizer.mjs +7 -0
  125. package/dist/parser/hybrid-parser.js +7 -0
  126. package/dist/parser/hybrid-parser.mjs +7 -0
  127. package/dist/parser/parser-types.d.ts +8 -28
  128. package/dist/parser/parser.d.ts +3 -7
  129. package/dist/parser/pratt-parser.d.ts +0 -3
  130. package/dist/parser/runtime.d.ts +4 -0
  131. package/dist/parser/semantic-integration.d.ts +17 -0
  132. package/dist/parser/types.d.ts +7 -1
  133. package/dist/reference/index.js +91 -0
  134. package/dist/reference/index.mjs +91 -0
  135. package/dist/registry/index.js +12866 -5876
  136. package/dist/registry/index.mjs +12866 -5876
  137. package/dist/registry/universal-types.d.ts +2 -1
  138. package/dist/runtime/command-adapter.d.ts +23 -16
  139. package/dist/runtime/plugin.d.ts +14 -0
  140. package/dist/runtime/runtime-base.d.ts +32 -7
  141. package/dist/runtime/runtime-factory.d.ts +3 -3
  142. package/dist/runtime/runtime.d.ts +2 -2
  143. package/dist/test-setup.d.ts +1 -0
  144. package/dist/types/base-types.d.ts +3 -0
  145. package/dist/types/feature-types.d.ts +1 -1
  146. package/dist/types/index.d.ts +2 -2
  147. package/package.json +26 -20
  148. package/vocab/htmx/ar.js +60 -0
  149. package/vocab/htmx/bn.js +49 -0
  150. package/vocab/htmx/de.js +60 -0
  151. package/vocab/htmx/en.js +21 -0
  152. package/vocab/htmx/es.js +60 -0
  153. package/vocab/htmx/fr.js +59 -0
  154. package/vocab/htmx/he.js +40 -0
  155. package/vocab/htmx/hi.js +60 -0
  156. package/vocab/htmx/id.js +57 -0
  157. package/vocab/htmx/it.js +58 -0
  158. package/vocab/htmx/ja.js +60 -0
  159. package/vocab/htmx/ko.js +60 -0
  160. package/vocab/htmx/ms.js +35 -0
  161. package/vocab/htmx/pl.js +60 -0
  162. package/vocab/htmx/pt.js +60 -0
  163. package/vocab/htmx/qu.js +60 -0
  164. package/vocab/htmx/ru.js +60 -0
  165. package/vocab/htmx/sw.js +59 -0
  166. package/vocab/htmx/th.js +49 -0
  167. package/vocab/htmx/tl.js +33 -0
  168. package/vocab/htmx/tr.js +60 -0
  169. package/vocab/htmx/uk.js +60 -0
  170. package/vocab/htmx/vi.js +51 -0
  171. package/vocab/htmx/zh.js +60 -0
  172. package/dist/bundles/test-minimal.d.ts +0 -3
  173. package/dist/bundles/test-standard.d.ts +0 -3
  174. package/dist/chunks/bridge-BlRqsZT4.js +0 -2
  175. package/dist/chunks/browser-modular-AbV0Ql4i.js +0 -2
  176. package/dist/chunks/feature-eventsource-B5F2-H1r.js +0 -2
  177. package/dist/chunks/feature-webworker-3bAp0ac9.js +0 -2
  178. package/dist/chunks/index-BDYQHwCF.js +0 -2
  179. package/dist/compatibility/browser-bundle-minimal.d.ts +0 -8
  180. package/dist/compatibility/browser-bundle-standard.d.ts +0 -8
  181. package/dist/compatibility/hyperscript-tests/test-adapter.d.ts +0 -13
  182. package/dist/core/base-expression-evaluator.d.ts +0 -74
  183. package/dist/core/binary-expression-evaluator.d.ts +0 -7
  184. package/dist/core/call-expression-evaluator.d.ts +0 -7
  185. package/dist/core/configurable-expression-evaluator.d.ts +0 -5
  186. package/dist/core/lazy-expression-evaluator.d.ts +0 -22
  187. package/dist/core/parser.d.ts +0 -21
  188. package/dist/core/selector-evaluator.d.ts +0 -15
  189. package/dist/core/template-literal-evaluator.d.ts +0 -5
  190. package/dist/expressions/comparison/index.d.ts +0 -80
  191. package/dist/expressions/comparison/utils.d.ts +0 -2
  192. package/dist/expressions/conversion/impl/bridge.d.ts +0 -117
  193. package/dist/expressions/logical/impl/pattern-matching.d.ts +0 -58
  194. package/dist/expressions/positional/impl/bridge.d.ts +0 -95
  195. package/dist/expressions/property/index.d.ts +0 -55
  196. package/dist/expressions/references/impl/bridge.d.ts +0 -54
  197. package/dist/extensions/index.d.ts +0 -3
  198. package/dist/extensions/tailwind.d.ts +0 -22
  199. package/dist/mod.d.ts +0 -63
  200. package/dist/parser/expression-parser.d.ts +0 -6
  201. package/dist/runtime/runtime-experimental.d.ts +0 -18
  202. package/dist/scripts/code-generator.d.ts +0 -64
  203. package/dist/scripts/generate-missing-commands.d.ts +0 -4
@@ -1,78 +1,12 @@
1
- function ok(value) {
2
- return { ok: true, value };
3
- }
4
- function err(error) {
5
- return { ok: false, error };
6
- }
7
-
8
- function checkDebugEnabled() {
9
- if (typeof localStorage !== 'undefined') {
10
- try {
11
- const ls = localStorage;
12
- const setting = ls.getItem('hyperfixi:debug') || ls.getItem('lokascript:debug');
13
- if (setting === '*' || setting === 'true')
14
- return true;
15
- }
16
- catch {
1
+ function createExpressionRegistry(...categories) {
2
+ const map = new Map();
3
+ for (const category of categories) {
4
+ for (const [name, impl] of Object.entries(category)) {
5
+ map.set(name, impl);
17
6
  }
18
7
  }
19
- if (typeof window !== 'undefined' && window.__HYPERFIXI_DEBUG__) {
20
- return true;
21
- }
22
- if (typeof process !== 'undefined' && process.env?.HYPERFIXI_DEBUG === 'true') {
23
- return true;
24
- }
25
- return false;
8
+ return map;
26
9
  }
27
- const isDebugEnabled = checkDebugEnabled();
28
- const DEBUG = {
29
- commands: isDebugEnabled,
30
- events: isDebugEnabled,
31
- parsing: isDebugEnabled,
32
- expressions: isDebugEnabled,
33
- styles: isDebugEnabled,
34
- runtime: isDebugEnabled,
35
- loops: isDebugEnabled,
36
- async: isDebugEnabled,
37
- };
38
- const debug = {
39
- command: (...args) => {
40
- if (DEBUG.commands)
41
- console.log('🔧', ...args);
42
- },
43
- event: (...args) => {
44
- if (DEBUG.events)
45
- console.log('🎯', ...args);
46
- },
47
- parse: (...args) => {
48
- if (DEBUG.parsing)
49
- console.log('📝', ...args);
50
- },
51
- expr: (...args) => {
52
- if (DEBUG.expressions)
53
- console.log('🔍', ...args);
54
- },
55
- expressions: (...args) => {
56
- if (DEBUG.expressions)
57
- console.log('🔍', ...args);
58
- },
59
- style: (...args) => {
60
- if (DEBUG.styles)
61
- console.log('🎨', ...args);
62
- },
63
- runtime: (...args) => {
64
- if (DEBUG.runtime)
65
- console.log('🚀', ...args);
66
- },
67
- loop: (...args) => {
68
- if (DEBUG.loops)
69
- console.log('🔁', ...args);
70
- },
71
- async: (...args) => {
72
- if (DEBUG.async)
73
- console.log('⏳', ...args);
74
- },
75
- };
76
10
 
77
11
  class ExpressionTypeRegistry {
78
12
  constructor(config = {}) {
@@ -327,1473 +261,104 @@ class ExpressionTypeRegistry {
327
261
  isType: (v) => typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof Element),
328
262
  defaultValue: {},
329
263
  description: 'Plain JavaScript object',
330
- coerceFrom: {
331
- String: v => {
332
- try {
333
- const parsed = JSON.parse(v);
334
- if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
335
- return parsed;
336
- }
337
- }
338
- catch {
339
- }
340
- return null;
341
- },
342
- Array: v => {
343
- const arr = v;
344
- const obj = {};
345
- arr.forEach((item, index) => {
346
- obj[String(index)] = item;
347
- });
348
- return obj;
349
- },
350
- },
351
- });
352
- this.register({
353
- name: 'Null',
354
- hyperscriptType: 'null',
355
- tsType: 'null',
356
- isType: (v) => v === null,
357
- defaultValue: null,
358
- description: 'Null value',
359
- });
360
- this.register({
361
- name: 'Undefined',
362
- hyperscriptType: 'undefined',
363
- tsType: 'undefined',
364
- isType: (v) => v === undefined,
365
- defaultValue: undefined,
366
- description: 'Undefined value',
367
- });
368
- this.register({
369
- name: 'Function',
370
- hyperscriptType: 'function',
371
- tsType: 'Function',
372
- isType: (v) => typeof v === 'function',
373
- defaultValue: null,
374
- description: 'JavaScript function',
375
- });
376
- this.register({
377
- name: 'Event',
378
- hyperscriptType: 'event',
379
- tsType: 'Event',
380
- isType: (v) => v instanceof Event,
381
- defaultValue: null,
382
- description: 'DOM Event',
383
- });
384
- this.register({
385
- name: 'NodeList',
386
- hyperscriptType: 'element-list',
387
- tsType: 'NodeList',
388
- isType: (v) => v instanceof NodeList,
389
- defaultValue: null,
390
- description: 'DOM NodeList (typically from querySelectorAll)',
391
- coerceFrom: {
392
- Array: v => {
393
- return null;
394
- },
395
- },
396
- });
397
- this.register({
398
- name: 'Unknown',
399
- hyperscriptType: 'unknown',
400
- tsType: 'unknown',
401
- isType: (_v) => true,
402
- defaultValue: null,
403
- description: 'Unknown/any value type',
404
- });
405
- }
406
- }
407
- const expressionTypeRegistry = new ExpressionTypeRegistry();
408
-
409
- function isString(value) {
410
- const stringType = expressionTypeRegistry.get('String');
411
- return stringType ? stringType.isType(value) : typeof value === 'string';
412
- }
413
- function isNumber(value) {
414
- const numberType = expressionTypeRegistry.get('Number');
415
- return numberType ? numberType.isType(value) : typeof value === 'number';
416
- }
417
- function isBoolean(value) {
418
- const boolType = expressionTypeRegistry.get('Boolean');
419
- return boolType ? boolType.isType(value) : typeof value === 'boolean';
420
- }
421
- function isObject(value) {
422
- const objectType = expressionTypeRegistry.get('Object');
423
- return objectType ? objectType.isType(value) : typeof value === 'object' && value !== null;
424
- }
425
- function isFunction(value) {
426
- const funcType = expressionTypeRegistry.get('Function');
427
- return funcType ? funcType.isType(value) : typeof value === 'function';
428
- }
429
-
430
- function isInputElement(el) {
431
- return (el !== null && typeof el === 'object' && 'tagName' in el && el.tagName === 'INPUT');
432
- }
433
- function isFormElement(el) {
434
- if (el === null || typeof el !== 'object' || !('tagName' in el)) {
435
- return false;
436
- }
437
- const tag = el.tagName;
438
- return tag === 'INPUT' || tag === 'SELECT' || tag === 'TEXTAREA';
439
- }
440
- function isHTMLElement$1(el) {
441
- return (el !== null &&
442
- typeof el === 'object' &&
443
- 'nodeType' in el &&
444
- el.nodeType === 1 &&
445
- 'style' in el);
446
- }
447
- function isOptionElement(el) {
448
- return (el !== null &&
449
- typeof el !== 'undefined' &&
450
- typeof el === 'object' &&
451
- 'tagName' in el &&
452
- el.tagName === 'OPTION');
453
- }
454
-
455
- function isElement(value) {
456
- return value instanceof Element;
457
- }
458
- function isHTMLElement(value) {
459
- return value instanceof HTMLElement;
460
- }
461
- const BOOLEAN_ATTRIBUTES = new Set([
462
- 'disabled',
463
- 'readonly',
464
- 'required',
465
- 'checked',
466
- 'selected',
467
- 'hidden',
468
- 'open',
469
- 'autofocus',
470
- 'autoplay',
471
- 'controls',
472
- 'loop',
473
- 'muted',
474
- 'multiple',
475
- 'reversed',
476
- 'defer',
477
- 'async',
478
- 'novalidate',
479
- 'formnovalidate',
480
- 'ismap',
481
- ]);
482
- function accessAttribute(element, attrName) {
483
- if (BOOLEAN_ATTRIBUTES.has(attrName.toLowerCase())) {
484
- return element.hasAttribute(attrName);
485
- }
486
- return element.getAttribute(attrName);
487
- }
488
- function hasAttribute(element, attrName) {
489
- return element.hasAttribute(attrName);
490
- }
491
- const SPECIAL_DOM_PROPERTIES = {
492
- id: el => el.id,
493
- classname: el => el.className,
494
- class: el => el.className,
495
- tagname: el => el.tagName.toLowerCase(),
496
- innertext: el => el.textContent?.trim(),
497
- innerHTML: el => el.innerHTML,
498
- outerhtml: el => el.outerHTML,
499
- value: el => (isFormElement(el) ? el.value : undefined),
500
- checked: el => (isInputElement(el) ? el.checked : undefined),
501
- disabled: el => ('disabled' in el ? el.disabled : undefined),
502
- selected: el => (isOptionElement(el) ? el.selected : undefined),
503
- tabindex: el => (isHTMLElement$1(el) ? el.tabIndex : undefined),
504
- hidden: el => (isHTMLElement$1(el) ? el.hidden : undefined),
505
- style: el => getComputedStyle(el),
506
- children: el => Array.from(el.children),
507
- parent: el => el.parentElement,
508
- firstchild: el => el.firstElementChild,
509
- lastchild: el => el.lastElementChild,
510
- nextsibling: el => el.nextElementSibling,
511
- previoussibling: el => el.previousElementSibling,
512
- values: el => collectFormValues(el),
513
- };
514
- function collectFormValues(el) {
515
- if (el instanceof HTMLFormElement)
516
- return new FormData(el);
517
- const fd = new FormData();
518
- el.querySelectorAll('input, select, textarea').forEach((input) => {
519
- const name = input.getAttribute('name');
520
- if (name && 'value' in input)
521
- fd.append(name, input.value);
522
- });
523
- return fd;
524
- }
525
- function getElementProperty(element, property) {
526
- if (property.startsWith('computed-')) {
527
- const cssProperty = property.slice('computed-'.length);
528
- if (isHTMLElement(element)) {
529
- const computedStyle = getComputedStyle(element);
530
- return computedStyle.getPropertyValue(cssProperty);
531
- }
532
- return undefined;
533
- }
534
- if (property.startsWith('@')) {
535
- const attrName = property.slice(1);
536
- return accessAttribute(element, attrName);
537
- }
538
- const specialHandler = SPECIAL_DOM_PROPERTIES[property.toLowerCase()];
539
- if (specialHandler) {
540
- return specialHandler(element);
541
- }
542
- if (hasAttribute(element, property)) {
543
- return accessAttribute(element, property);
544
- }
545
- const value = element[property];
546
- if (isFunction(value)) {
547
- return value.bind(element);
548
- }
549
- return value;
550
- }
551
-
552
- function extractPropertyName(property) {
553
- if (typeof property === 'string')
554
- return property;
555
- if (property && typeof property === 'object') {
556
- if (typeof property.name === 'string')
557
- return property.name;
558
- if (typeof property.value === 'string')
559
- return property.value;
560
- }
561
- return property;
562
- }
563
-
564
- function getDoc(context) {
565
- return context.me?.ownerDocument ?? (typeof document !== 'undefined' ? document : null);
566
- }
567
- function evaluateSelector(node, context) {
568
- let selector = node.value;
569
- if (selector.startsWith('<') && selector.endsWith('/>')) {
570
- selector = selector.slice(1, -2).trim();
571
- }
572
- const doc = getDoc(context);
573
- if (!doc) {
574
- return [];
575
- }
576
- const elements = doc.querySelectorAll(selector);
577
- const isEl = (el) => el && typeof el === 'object' && el.nodeType === 1 && typeof el.tagName === 'string';
578
- return Array.from(elements).filter(isEl);
579
- }
580
- function evaluateCSSSelector(node, context) {
581
- let selector = node.selector;
582
- if (selector.startsWith('<') && selector.endsWith('/>')) {
583
- selector = selector.slice(1, -2).trim();
584
- }
585
- const doc = getDoc(context);
586
- if (!doc) {
587
- return node.selectorType === 'id' ? null : [];
588
- }
589
- if (node.selectorType === 'id') {
590
- const id = selector.startsWith('#') ? selector.slice(1) : selector;
591
- return doc.getElementById(id);
592
- }
593
- else if (node.selectorType === 'class') {
594
- const escapedSelector = selector.replace(/:/g, '\\:');
595
- const elements = doc.querySelectorAll(escapedSelector);
596
- return Array.from(elements).filter((el) => el instanceof HTMLElement);
597
- }
598
- const elements = doc.querySelectorAll(selector);
599
- return Array.from(elements).filter((el) => el instanceof HTMLElement);
600
- }
601
- function evaluateIdSelector(node, context) {
602
- const doc = getDoc(context);
603
- if (!doc) {
604
- return null;
605
- }
606
- const id = node.value.startsWith('#') ? node.value.slice(1) : node.value;
607
- return doc.getElementById(id);
608
- }
609
- function evaluateQueryReference(node, context) {
610
- let selector = node.selector;
611
- if (selector.startsWith('<') && selector.endsWith('/>')) {
612
- selector = selector.slice(1, -2).trim();
613
- }
614
- const doc = getDoc(context);
615
- if (!doc) {
616
- return [];
617
- }
618
- try {
619
- return doc.querySelectorAll(selector);
620
- }
621
- catch {
622
- return doc.createDocumentFragment().childNodes;
623
- }
624
- }
625
-
626
- function lookupTemplateVariable(name, context) {
627
- if (context.locals?.has(name))
628
- return context.locals.get(name);
629
- if (context.globals?.has(name))
630
- return context.globals.get(name);
631
- if (context.variables?.has(name))
632
- return context.variables.get(name);
633
- if (name === 'me')
634
- return context.me;
635
- if (name === 'it')
636
- return context.it;
637
- if (name === 'result')
638
- return context.result;
639
- return undefined;
640
- }
641
- async function resolveTemplateVariable(varName, context) {
642
- if (varName.includes('.')) {
643
- const parts = varName.split('.');
644
- let value = lookupTemplateVariable(parts[0], context);
645
- for (let i = 1; i < parts.length && value != null; i++) {
646
- value = value[parts[i]];
647
- }
648
- return value;
649
- }
650
- return lookupTemplateVariable(varName, context);
651
- }
652
- async function resolveValue(name, context) {
653
- debug.expressions(`RESOLVE: Looking for '${name}' in context`, {
654
- hasInLocals: context.locals.has(name),
655
- localsKeys: Array.from(context.locals.keys()),
656
- value: context.locals.get(name),
657
- });
658
- if (context.locals.has(name)) {
659
- const value = context.locals.get(name);
660
- debug.expressions(`RESOLVE: Found '${name}' in locals:`, value);
661
- return value;
662
- }
663
- if (context.globals && context.globals.has(name)) {
664
- const value = context.globals.get(name);
665
- debug.expressions(`RESOLVE: Found '${name}' in globals:`, value);
666
- return value;
667
- }
668
- if (context.variables && context.variables.has(name)) {
669
- const value = context.variables.get(name);
670
- debug.expressions(`RESOLVE: Found '${name}' in variables (legacy):`, value);
671
- return value;
672
- }
673
- const num = Number(name);
674
- if (!isNaN(num)) {
675
- return num;
676
- }
677
- if ((name.startsWith('"') && name.endsWith('"')) ||
678
- (name.startsWith("'") && name.endsWith("'"))) {
679
- return name.slice(1, -1);
680
- }
681
- if (name.includes('.')) {
682
- const parts = name.split('.');
683
- const baseName = parts[0];
684
- let obj = null;
685
- if (context.locals.has(baseName)) {
686
- obj = context.locals.get(baseName);
687
- }
688
- else if (context.globals && context.globals.has(baseName)) {
689
- obj = context.globals.get(baseName);
690
- }
691
- else if (context.variables && context.variables.has(baseName)) {
692
- obj = context.variables.get(baseName);
693
- }
694
- if (obj !== null && obj !== undefined) {
695
- for (let i = 1; i < parts.length; i++) {
696
- if (obj === null || obj === undefined) {
697
- debug.expressions(`RESOLVE: Property access failed at '${parts[i - 1]}'`);
698
- return undefined;
699
- }
700
- obj = obj[parts[i]];
701
- }
702
- debug.expressions(`RESOLVE: Property access '${name}' =`, obj);
703
- return obj;
704
- }
705
- }
706
- return name;
707
- }
708
- async function evaluateSimpleExpression(exprCode, context) {
709
- debug.expressions('EVAL: Evaluating expression:', exprCode);
710
- const ternaryMatch = exprCode.match(/^(.+?)\s*\?(?![\.\[])\s*(.+?)\s*:\s*(.+)$/);
711
- if (ternaryMatch) {
712
- const [, conditionExpr, trueExpr, falseExpr] = ternaryMatch;
713
- debug.expressions('EVAL: Parsed ternary:', { conditionExpr, trueExpr, falseExpr });
714
- const conditionValue = await resolveValue(conditionExpr.trim(), context);
715
- debug.expressions('EVAL: Ternary condition value:', conditionValue);
716
- if (conditionValue) {
717
- const trueValue = await resolveValue(trueExpr.trim(), context);
718
- debug.expressions('EVAL: Ternary returned true branch:', trueValue);
719
- return trueValue;
720
- }
721
- else {
722
- const falseValue = await resolveValue(falseExpr.trim(), context);
723
- debug.expressions('EVAL: Ternary returned false branch:', falseValue);
724
- return falseValue;
725
- }
726
- }
727
- const arithmeticMatch = exprCode.match(/^([a-zA-Z_$][a-zA-Z0-9_$]*|\d+(?:\.\d+)?)\s*([\+\-\*\/\%])\s*([a-zA-Z_$][a-zA-Z0-9_$]*|\d+(?:\.\d+)?)$/);
728
- if (arithmeticMatch) {
729
- const [, left, operator, right] = arithmeticMatch;
730
- debug.expressions('EVAL: Parsed arithmetic:', { left, operator, right });
731
- const leftValue = await resolveValue(left.trim(), context);
732
- const rightValue = await resolveValue(right.trim(), context);
733
- debug.expressions('EVAL: Resolved values:', { leftValue, rightValue });
734
- const leftNum = Number(leftValue);
735
- const rightNum = Number(rightValue);
736
- if (!isNaN(leftNum) && !isNaN(rightNum)) {
737
- let result;
738
- switch (operator) {
739
- case '+':
740
- result = leftNum + rightNum;
741
- break;
742
- case '-':
743
- result = leftNum - rightNum;
744
- break;
745
- case '*':
746
- result = leftNum * rightNum;
747
- break;
748
- case '/':
749
- result = leftNum / rightNum;
750
- break;
751
- case '%':
752
- result = leftNum % rightNum;
753
- break;
754
- default:
755
- result = leftNum;
756
- }
757
- debug.expressions('EVAL: Arithmetic result:', result);
758
- return result;
759
- }
760
- }
761
- const fallback = await resolveValue(exprCode.trim(), context);
762
- debug.expressions('EVAL: Fallback result:', fallback);
763
- return fallback;
764
- }
765
- async function evaluateTemplateLiteral(node, context) {
766
- let template = node.value || '';
767
- debug.expressions('TEMPLATE LITERAL: Evaluating', { template, node });
768
- const varPattern = /\$([a-zA-Z_][a-zA-Z0-9_]*(?:\.[a-zA-Z_][a-zA-Z0-9_]*)*)/g;
769
- const matches = [];
770
- let m;
771
- while ((m = varPattern.exec(template)) !== null) {
772
- if (template[m.index + 1] === '{')
773
- continue;
774
- matches.push({ match: m[0], varName: m[1], index: m.index });
775
- }
776
- for (let i = matches.length - 1; i >= 0; i--) {
777
- const { match, varName, index } = matches[i];
778
- const value = await resolveTemplateVariable(varName, context);
779
- debug.expressions(`TEMPLATE: $${varName} resolved to`, value);
780
- template =
781
- template.slice(0, index) + String(value ?? '') + template.slice(index + match.length);
782
- }
783
- let result = '';
784
- let j = 0;
785
- while (j < template.length) {
786
- const exprStart = template.indexOf('${', j);
787
- if (exprStart === -1) {
788
- result += template.slice(j);
789
- break;
790
- }
791
- result += template.slice(j, exprStart);
792
- let depth = 1;
793
- let exprEnd = exprStart + 2;
794
- while (exprEnd < template.length && depth > 0) {
795
- if (template[exprEnd] === '{')
796
- depth++;
797
- if (template[exprEnd] === '}')
798
- depth--;
799
- if (depth > 0)
800
- exprEnd++;
801
- }
802
- if (depth !== 0) {
803
- throw new Error(`Unterminated template expression in: ${template}`);
804
- }
805
- const exprCode = template.slice(exprStart + 2, exprEnd);
806
- debug.expressions('TEMPLATE: Evaluating expression:', exprCode);
807
- let value;
808
- const trimmed = exprCode.trim();
809
- if (context.locals.has(trimmed)) {
810
- value = context.locals.get(trimmed);
811
- debug.expressions(`TEMPLATE: Found in locals: ${trimmed} =`, value);
812
- }
813
- else if (context.globals && context.globals.has(trimmed)) {
814
- value = context.globals.get(trimmed);
815
- debug.expressions(`TEMPLATE: Found in globals: ${trimmed} =`, value);
816
- }
817
- else if (context.variables && context.variables.has(trimmed)) {
818
- value = context.variables.get(trimmed);
819
- debug.expressions(`TEMPLATE: Found in variables (legacy): ${trimmed} =`, value);
820
- }
821
- else {
822
- value = await evaluateSimpleExpression(exprCode, context);
823
- debug.expressions(`TEMPLATE: Evaluated expression "${exprCode}" =`, value);
824
- }
825
- result += String(value);
826
- j = exprEnd + 1;
827
- }
828
- return result;
829
- }
830
-
831
- function coerceArithmeticOperand(value) {
832
- if (Array.isArray(value) && value.length === 1) {
833
- value = value[0];
834
- }
835
- if (value !== null &&
836
- typeof value === 'object' &&
837
- typeof value.textContent === 'string') {
838
- const text = value.value ?? value.textContent;
839
- if (text !== null && text !== undefined) {
840
- const trimmed = String(text).trim();
841
- if (trimmed === '')
842
- return 0;
843
- const num = parseFloat(trimmed);
844
- return isNaN(num) ? trimmed : num;
845
- }
846
- return 0;
847
- }
848
- return value;
849
- }
850
- async function evaluateBinaryExpression(node, context, evaluate, unwrap, expressionRegistry, evaluateSelector) {
851
- const { operator, left, right } = node;
852
- if (operator === 'in' && left.type === 'selector') {
853
- let selector = left.value;
854
- if (selector.startsWith('<') && selector.endsWith('/>')) {
855
- selector = selector.slice(1, -2).trim();
856
- }
857
- const contextElement = unwrap(await evaluate(right, context));
858
- if (!contextElement || typeof contextElement.querySelector !== 'function') {
859
- throw new Error(`'in' operator requires a DOM element as the right operand (got: ${typeof contextElement})`);
860
- }
861
- const nodeList = contextElement.querySelectorAll(selector);
862
- return Array.from(nodeList);
863
- }
864
- if (operator === 'in' && left.type === 'queryReference') {
865
- let selector = left.selector;
866
- if (selector.startsWith('<') && selector.endsWith('/>')) {
867
- selector = selector.slice(1, -2).trim();
868
- }
869
- const contextElement = unwrap(await evaluate(right, context));
870
- if (!contextElement || typeof contextElement.querySelector !== 'function') {
871
- throw new Error(`'in' operator requires a DOM element as the right operand (got: ${typeof contextElement})`);
872
- }
873
- const nodeList = contextElement.querySelectorAll(selector);
874
- return Array.from(nodeList);
875
- }
876
- if (operator === 'in') {
877
- let positionalOp = null;
878
- let selector = null;
879
- if (left.type === 'positionalExpression') {
880
- positionalOp = left.operator;
881
- const selectorArg = left.argument;
882
- if (selectorArg?.type === 'cssSelector') {
883
- selector = selectorArg.selector;
884
- }
885
- else if (selectorArg?.type === 'selector') {
886
- selector = selectorArg.value;
887
- }
888
- else if (selectorArg?.type === 'classSelector') {
889
- selector = '.' + selectorArg.className;
890
- }
891
- else if (selectorArg?.type === 'idSelector') {
892
- selector = '#' + selectorArg.id;
893
- }
894
- else if (selectorArg) {
895
- selector = String(await evaluate(selectorArg, context));
896
- }
897
- }
898
- else if (left.type === 'memberExpression' &&
899
- left.object?.type === 'identifier' &&
900
- (left.object.name === 'first' || left.object.name === 'last')) {
901
- positionalOp = left.object.name;
902
- if (left.property?.type === 'identifier' && left.property.name) {
903
- selector = '.' + left.property.name;
904
- }
905
- }
906
- else if (left.type === 'callExpression' &&
907
- left.callee?.type === 'identifier' &&
908
- (left.callee.name === 'first' || left.callee.name === 'last')) {
909
- positionalOp = left.callee.name;
910
- const selectorArg = left.arguments?.[0];
911
- if (selectorArg?.type === 'selector') {
912
- selector = selectorArg.value;
913
- }
914
- else if (selectorArg?.type === 'cssSelector') {
915
- selector = selectorArg.selector;
916
- }
917
- else if (selectorArg?.type === 'classSelector') {
918
- selector = '.' + selectorArg.className;
919
- }
920
- else if (selectorArg?.type === 'idSelector') {
921
- selector = '#' + selectorArg.id;
922
- }
923
- else if (selectorArg) {
924
- selector = String(await evaluate(selectorArg, context));
925
- }
926
- }
927
- if (positionalOp && selector) {
928
- const scopeElement = unwrap(await evaluate(right, context));
929
- if (!scopeElement || typeof scopeElement.querySelectorAll !== 'function') {
930
- return undefined;
931
- }
932
- const nodeList = scopeElement.querySelectorAll(selector);
933
- const elements = Array.from(nodeList);
934
- if (positionalOp === 'first') {
935
- return elements.length > 0 ? elements[0] : undefined;
936
- }
937
- else if (positionalOp === 'last') {
938
- return elements.length > 0 ? elements[elements.length - 1] : undefined;
939
- }
940
- return elements;
941
- }
942
- }
943
- if (operator === 'matches' &&
944
- (right.type === 'selector' || right.type === 'cssSelector' || right.type === 'classSelector')) {
945
- const leftValue = await evaluate(left, context);
946
- const selectorStr = right.value || right.selector;
947
- if (leftValue && typeof leftValue.matches === 'function') {
948
- try {
949
- return leftValue.matches(selectorStr);
950
- }
951
- catch {
952
- return false;
953
- }
954
- }
955
- return false;
956
- }
957
- const leftValue = await evaluate(left, context);
958
- const rightValue = await evaluate(right, context);
959
- if (operator === 'has' || operator === 'have') {
960
- if (leftValue instanceof Element) {
961
- if ((right.type === 'cssSelector' && right.selectorType === 'class') ||
962
- (right.type === 'selector' && right.value?.startsWith('.'))) {
963
- const className = right.selector?.slice(1) || right.value?.slice(1) || '';
964
- return leftValue.classList.contains(className);
965
- }
966
- if (right.type === 'attributeAccess' || right.type === 'attributeRef') {
967
- const attrName = right.attributeName || right.name || right.value?.replace(/^@/, '') || '';
968
- return leftValue.hasAttribute(attrName);
969
- }
970
- if (right.type === 'cssSelector' && right.selectorType === 'attribute') {
971
- const attrName = (right.selector || right.value || '').replace(/^@/, '');
972
- return leftValue.hasAttribute(attrName);
973
- }
974
- if ((right.type === 'cssSelector' && right.selectorType === 'id') ||
975
- right.type === 'idSelector') {
976
- const id = (right.selector || right.value || '').replace(/^#/, '');
977
- return leftValue.querySelector(`#${CSS.escape(id)}`) !== null;
978
- }
979
- if (right.type === 'selector' || right.type === 'queryReference') {
980
- let sel = right.value || right.selector || '';
981
- if (sel.startsWith('<') && sel.endsWith('/>')) {
982
- sel = sel.slice(1, -2).trim();
983
- }
984
- try {
985
- return leftValue.querySelector(sel) !== null;
986
- }
987
- catch {
988
- return false;
989
- }
990
- }
991
- if (right.type === 'cssSelector') {
992
- const sel = right.selector || '';
993
- try {
994
- return leftValue.querySelector(sel) !== null;
995
- }
996
- catch {
997
- return false;
998
- }
999
- }
1000
- }
1001
- if (Array.isArray(leftValue)) {
1002
- return leftValue.includes(rightValue);
1003
- }
1004
- if (typeof leftValue === 'string') {
1005
- return leftValue.includes(String(rightValue));
1006
- }
1007
- return false;
1008
- }
1009
- switch (operator) {
1010
- case '>':
1011
- case 'is greater than':
1012
- return leftValue > rightValue;
1013
- case '<':
1014
- case 'is less than':
1015
- return leftValue < rightValue;
1016
- case '>=':
1017
- case 'is greater than or equal to':
1018
- return leftValue >= rightValue;
1019
- case '<=':
1020
- case 'is less than or equal to':
1021
- return leftValue <= rightValue;
1022
- case '==':
1023
- case 'equals':
1024
- case 'is equal to':
1025
- return leftValue == rightValue;
1026
- case '===':
1027
- case 'is really equal to':
1028
- case 'really equals':
1029
- return leftValue === rightValue;
1030
- case '!=':
1031
- case 'is not equal to':
1032
- return leftValue != rightValue;
1033
- case '!==':
1034
- case 'is not really equal to':
1035
- return leftValue !== rightValue;
1036
- case '+': {
1037
- const coercedLeft = coerceArithmeticOperand(leftValue);
1038
- const coercedRight = coerceArithmeticOperand(rightValue);
1039
- const shouldUseStringConcatenation = typeof coercedLeft === 'string' || typeof coercedRight === 'string';
1040
- if (shouldUseStringConcatenation) {
1041
- const stringConcatExpr = expressionRegistry.get('stringConcatenation');
1042
- if (stringConcatExpr) {
1043
- debug.expressions('Using string concatenation for:', {
1044
- leftValue: coercedLeft,
1045
- rightValue: coercedRight,
1046
- });
1047
- const result = await stringConcatExpr.evaluate(context, {
1048
- left: coercedLeft,
1049
- right: coercedRight,
1050
- });
1051
- return result.success ? result.value : coercedLeft + coercedRight;
1052
- }
1053
- }
1054
- else {
1055
- const additionExpr = expressionRegistry.get('addition');
1056
- if (additionExpr) {
1057
- debug.expressions('Using numeric addition for:', {
1058
- leftValue: coercedLeft,
1059
- rightValue: coercedRight,
1060
- });
1061
- const result = await additionExpr.evaluate(context, {
1062
- left: coercedLeft,
1063
- right: coercedRight,
1064
- });
1065
- return result.success ? result.value : coercedLeft + coercedRight;
1066
- }
1067
- }
1068
- return coercedLeft + coercedRight;
1069
- }
1070
- case '-':
1071
- return (coerceArithmeticOperand(leftValue) - coerceArithmeticOperand(rightValue));
1072
- case '*':
1073
- return (coerceArithmeticOperand(leftValue) * coerceArithmeticOperand(rightValue));
1074
- case '/':
1075
- return (coerceArithmeticOperand(leftValue) / coerceArithmeticOperand(rightValue));
1076
- case '%':
1077
- case 'mod':
1078
- return (coerceArithmeticOperand(leftValue) % coerceArithmeticOperand(rightValue));
1079
- case 'as':
1080
- const typeName = typeof rightValue === 'string'
1081
- ? rightValue
1082
- : right.type === 'identifier'
1083
- ? right.name
1084
- : right.type === 'literal'
1085
- ? right.value
1086
- : String(rightValue);
1087
- const asExpr = expressionRegistry.get('as');
1088
- return asExpr ? asExpr.evaluate(context, leftValue, typeName) : leftValue;
1089
- case '&&':
1090
- case 'and':
1091
- return leftValue && rightValue;
1092
- case '||':
1093
- case 'or':
1094
- return leftValue || rightValue;
1095
- case 'is':
1096
- return leftValue === rightValue;
1097
- case 'is not':
1098
- return leftValue !== rightValue;
1099
- case 'is a':
1100
- case 'is an':
1101
- const checkTypeName = right.type === 'identifier' ? right.name.toLowerCase() : String(rightValue).toLowerCase();
1102
- switch (checkTypeName) {
1103
- case 'string':
1104
- return typeof leftValue === 'string';
1105
- case 'number':
1106
- return typeof leftValue === 'number';
1107
- case 'boolean':
1108
- return typeof leftValue === 'boolean';
1109
- case 'object':
1110
- return typeof leftValue === 'object' && leftValue !== null;
1111
- case 'array':
1112
- return Array.isArray(leftValue);
1113
- case 'function':
1114
- return typeof leftValue === 'function';
1115
- case 'null':
1116
- return leftValue === null;
1117
- case 'undefined':
1118
- return leftValue === undefined;
1119
- default:
1120
- const typeNameStr = right.type === 'identifier' ? right.name : String(rightValue);
1121
- return leftValue != null && leftValue.constructor?.name === typeNameStr;
1122
- }
1123
- case 'is not a':
1124
- case 'is not an':
1125
- const negCheckTypeName = right.type === 'identifier' ? right.name.toLowerCase() : String(rightValue).toLowerCase();
1126
- switch (negCheckTypeName) {
1127
- case 'string':
1128
- return typeof leftValue !== 'string';
1129
- case 'number':
1130
- return typeof leftValue !== 'number';
1131
- case 'boolean':
1132
- return typeof leftValue !== 'boolean';
1133
- case 'object':
1134
- return !(typeof leftValue === 'object' && leftValue !== null);
1135
- case 'array':
1136
- return !Array.isArray(leftValue);
1137
- case 'function':
1138
- return typeof leftValue !== 'function';
1139
- case 'null':
1140
- return leftValue !== null;
1141
- case 'undefined':
1142
- return leftValue !== undefined;
1143
- default:
1144
- const negTypeNameStr = right.type === 'identifier' ? right.name : String(rightValue);
1145
- return !(leftValue != null && leftValue.constructor?.name === negTypeNameStr);
1146
- }
1147
- case '=':
1148
- if (left.type === 'identifier') {
1149
- const variableName = left.name;
1150
- if (variableName === 'result') {
1151
- context.result = rightValue;
1152
- }
1153
- else if (variableName === 'it') {
1154
- context.it = rightValue;
1155
- }
1156
- else if (variableName === 'you') {
1157
- context.you = rightValue;
1158
- }
1159
- else {
1160
- context.locals.set(variableName, rightValue);
1161
- }
1162
- return rightValue;
1163
- }
1164
- else {
1165
- throw new Error('Left side of assignment must be an identifier');
1166
- }
1167
- case 'contains':
1168
- if (Array.isArray(leftValue)) {
1169
- return leftValue.includes(rightValue);
1170
- }
1171
- if (typeof leftValue === 'string') {
1172
- return leftValue.includes(String(rightValue));
1173
- }
1174
- if (leftValue && typeof leftValue.matches === 'function') {
1175
- return leftValue.matches(String(rightValue));
1176
- }
1177
- return false;
1178
- case 'include':
1179
- case 'includes':
1180
- if (Array.isArray(leftValue)) {
1181
- return leftValue.includes(rightValue);
1182
- }
1183
- if (typeof leftValue === 'string') {
1184
- return leftValue.includes(String(rightValue));
1185
- }
1186
- if (leftValue && typeof leftValue.matches === 'function') {
1187
- return leftValue.matches(String(rightValue));
1188
- }
1189
- return false;
1190
- case 'match':
1191
- case 'matches':
1192
- if (leftValue && typeof leftValue.matches === 'function') {
1193
- const selectorStr = typeof rightValue === 'string' ? rightValue : String(rightValue);
1194
- try {
1195
- return leftValue.matches(selectorStr);
1196
- }
1197
- catch {
1198
- return false;
1199
- }
1200
- }
1201
- return false;
1202
- case 'in':
1203
- const selectorIn = typeof leftValue === 'string' ? leftValue : String(leftValue);
1204
- const contextElementIn = rightValue;
1205
- if (!contextElementIn || typeof contextElementIn.querySelector !== 'function') {
1206
- if (Array.isArray(contextElementIn)) {
1207
- return contextElementIn.includes(leftValue);
1208
- }
1209
- if (typeof contextElementIn === 'object' && contextElementIn !== null) {
1210
- return selectorIn in contextElementIn;
1211
- }
1212
- throw new Error(`'in' operator requires a DOM element, array, or object as the right operand (got: ${typeof contextElementIn})`);
1213
- }
1214
- return contextElementIn.querySelector(selectorIn);
1215
- case ' ':
1216
- if (typeof leftValue === 'string' && typeof rightValue === 'string') {
1217
- return { command: leftValue, selector: rightValue };
1218
- }
1219
- if (left.type === 'identifier' && right.type === 'selector') {
1220
- return { command: left.name, selector: right.value };
1221
- }
1222
- return rightValue;
1223
- default:
1224
- throw new Error(`Unsupported binary operator: "${operator}" (length: ${operator.length})`);
1225
- }
1226
- }
1227
-
1228
- async function evaluateCallExpression(node, context, evaluate, unwrap, expressionRegistry, evaluateSelector) {
1229
- const { callee, arguments: args, isConstructor } = node;
1230
- if (isConstructor) {
1231
- const constructorName = callee.name;
1232
- const Constructor = context.globals?.get(constructorName) || window[constructorName];
1233
- if (typeof Constructor === 'function') {
1234
- const evaluatedArgs = await Promise.all(args.map((arg) => evaluate(arg, context)));
1235
- return new Constructor(...evaluatedArgs);
1236
- }
1237
- throw new Error(`Unknown constructor: ${constructorName}`);
1238
- }
1239
- if (callee.type === 'memberExpression' || callee.type === 'propertyAccess') {
1240
- return evaluateMethodCall(callee, args, context, evaluate, unwrap);
1241
- }
1242
- const functionName = callee.name || callee;
1243
- const expression = expressionRegistry.get(functionName);
1244
- if (expression) {
1245
- const selectorStringFunctions = ['closest', 'previous', 'next'];
1246
- const collectionFunctions = ['first', 'last', 'random', 'at'];
1247
- const needsSelectorString = selectorStringFunctions.includes(functionName);
1248
- const needsCollection = collectionFunctions.includes(functionName);
1249
- const evaluatedArgs = await Promise.all(args.map((arg) => {
1250
- if (needsSelectorString &&
1251
- arg &&
1252
- arg.type === 'selector' &&
1253
- typeof arg.value === 'string') {
1254
- return arg.value;
1255
- }
1256
- if (needsSelectorString &&
1257
- arg &&
1258
- arg.type === 'identifier' &&
1259
- typeof arg.name === 'string') {
1260
- return arg.name;
1261
- }
1262
- if (needsCollection && arg && arg.type === 'selector' && typeof arg.value === 'string') {
1263
- return evaluateSelector(arg, context);
1264
- }
1265
- return evaluate(arg, context);
1266
- }));
1267
- return expression.evaluate(context, ...evaluatedArgs);
1268
- }
1269
- const func = context.globals?.get(functionName) || window[functionName];
1270
- if (typeof func === 'function') {
1271
- const evaluatedArgs = await Promise.all(args.map((arg) => evaluate(arg, context)));
1272
- return func(...evaluatedArgs);
1273
- }
1274
- throw new Error(`Unknown function: ${functionName}`);
1275
- }
1276
- async function evaluateMethodCall(callee, args, context, evaluate, unwrap) {
1277
- try {
1278
- const object = await evaluate(callee.object, context);
1279
- const thisContext = unwrap(object);
1280
- if (thisContext === null || thisContext === undefined) {
1281
- throw new Error(`Cannot call method on null or undefined`);
1282
- }
1283
- const propertyName = extractPropertyName(callee.property);
1284
- if (!propertyName || typeof propertyName !== 'string') {
1285
- throw new Error(`Invalid method name: ${propertyName}`);
1286
- }
1287
- const func = thisContext[propertyName];
1288
- if (typeof func !== 'function') {
1289
- throw new Error(`Property "${propertyName}" is not a function on ${thisContext.constructor?.name || typeof thisContext}`);
1290
- }
1291
- const evaluatedArgs = await Promise.all(args.map((arg) => evaluate(arg, context)));
1292
- const result = func.apply(thisContext, evaluatedArgs);
1293
- return result;
1294
- }
1295
- catch (error) {
1296
- if (error instanceof Error) {
1297
- throw error;
1298
- }
1299
- throw new Error(`Failed to evaluate method call: ${error}`);
1300
- }
1301
- }
1302
-
1303
- class BaseExpressionEvaluator {
1304
- constructor() {
1305
- this.expressionRegistry = new Map();
1306
- }
1307
- registerCategory(expressions) {
1308
- Object.entries(expressions).forEach(([name, impl]) => {
1309
- this.expressionRegistry.set(name, impl);
1310
- });
1311
- }
1312
- unwrapSelectorResult(value) {
1313
- if (value instanceof NodeList && value.length > 0) {
1314
- return value[0];
1315
- }
1316
- if (Array.isArray(value) && value.length > 0) {
1317
- const firstElement = value[0];
1318
- const hasRegexProps = 'index' in value && 'input' in value;
1319
- if (hasRegexProps) {
1320
- return value;
1321
- }
1322
- if (firstElement instanceof Element || firstElement instanceof Node) {
1323
- return firstElement;
1324
- }
1325
- return value;
1326
- }
1327
- return value;
1328
- }
1329
- async evaluate(node, context) {
1330
- if (!node) {
1331
- debug.expressions('EVALUATOR: Received null/undefined node, returning null');
1332
- return null;
1333
- }
1334
- if (!node.type) {
1335
- console.error('EVALUATOR: Node missing type property:', node);
1336
- throw new Error(`Node missing type property: ${JSON.stringify(node)}`);
1337
- }
1338
- switch (node.type) {
1339
- case 'identifier':
1340
- return this.evaluateIdentifier(node, context);
1341
- case 'literal':
1342
- return this.evaluateLiteral(node, context);
1343
- case 'string':
1344
- return node.value ?? '';
1345
- case 'memberExpression':
1346
- return this.evaluateMemberExpression(node, context);
1347
- case 'binaryExpression':
1348
- return this.evaluateBinaryExpression(node, context);
1349
- case 'unaryExpression':
1350
- return this.evaluateUnaryExpression(node, context);
1351
- case 'callExpression':
1352
- return this.evaluateCallExpression(node, context);
1353
- case 'selector':
1354
- return this.evaluateSelector(node, context);
1355
- case 'dollarExpression':
1356
- return this.evaluateDollarExpression(node, context);
1357
- case 'possessiveExpression':
1358
- return this.evaluatePossessiveExpression(node, context);
1359
- case 'templateLiteral':
1360
- return this.evaluateTemplateLiteral(node, context);
1361
- case 'arrayLiteral':
1362
- return this.evaluateArrayLiteral(node, context);
1363
- case 'objectLiteral':
1364
- return this.evaluateObjectLiteral(node, context);
1365
- case 'conditionalExpression':
1366
- return this.evaluateConditionalExpression(node, context);
1367
- case 'cssSelector':
1368
- return this.evaluateCSSSelector(node, context);
1369
- case 'propertyAccess':
1370
- return this.evaluatePropertyAccess(node, context);
1371
- case 'propertyOfExpression':
1372
- return this.evaluatePropertyOfExpression(node, context);
1373
- case 'contextReference':
1374
- return this.evaluateContextReference(node, context);
1375
- case 'queryReference':
1376
- return this.evaluateQueryReference(node, context);
1377
- case 'idSelector':
1378
- return this.evaluateIdSelector(node, context);
1379
- case 'attributeAccess':
1380
- return this.evaluateAttributeAccess(node, context);
1381
- case 'asExpression':
1382
- return this.evaluateAsExpression(node, context);
1383
- default:
1384
- throw new Error(`Unsupported AST node type for evaluation: ${node.type}`);
1385
- }
1386
- }
1387
- async evaluateWithResult(node, context) {
1388
- try {
1389
- const value = await this.evaluate(node, context);
1390
- return ok(value);
1391
- }
1392
- catch (e) {
1393
- if (e instanceof Error) {
1394
- const error = e;
1395
- if (error.isHalt || error.message === 'HALT_EXECUTION') {
1396
- return err({ type: 'halt' });
1397
- }
1398
- if (error.isExit || error.message === 'EXIT_COMMAND') {
1399
- return err({ type: 'exit', returnValue: error.returnValue });
1400
- }
1401
- if (error.isBreak) {
1402
- return err({ type: 'break' });
1403
- }
1404
- if (error.isContinue) {
1405
- return err({ type: 'continue' });
1406
- }
1407
- if (error.isReturn) {
1408
- return err({ type: 'return', returnValue: error.returnValue });
1409
- }
1410
- }
1411
- throw e;
1412
- }
1413
- }
1414
- async evaluateArrayLiteral(node, context) {
1415
- const elements = node.elements || [];
1416
- const evaluatedElements = [];
1417
- for (const element of elements) {
1418
- const value = await this.evaluate(element, context);
1419
- evaluatedElements.push(value);
1420
- }
1421
- return evaluatedElements;
1422
- }
1423
- async evaluateObjectLiteral(node, context) {
1424
- const properties = node.properties || [];
1425
- const result = {};
1426
- for (const property of properties) {
1427
- let key;
1428
- if (property.key.type === 'identifier') {
1429
- key = property.key.name;
1430
- }
1431
- else if (property.key.type === 'literal') {
1432
- key = String(property.key.value);
1433
- }
1434
- else {
1435
- const evaluatedKey = await this.evaluate(property.key, context);
1436
- key = String(evaluatedKey);
1437
- }
1438
- const value = await this.evaluate(property.value, context);
1439
- result[key] = value;
1440
- }
1441
- return result;
1442
- }
1443
- async evaluateConditionalExpression(node, context) {
1444
- const test = await this.evaluate(node.test, context);
1445
- if (test) {
1446
- return this.evaluate(node.consequent, context);
1447
- }
1448
- else if (node.alternate) {
1449
- return this.evaluate(node.alternate, context);
1450
- }
1451
- return undefined;
1452
- }
1453
- async evaluateTemplateLiteral(node, context) {
1454
- return evaluateTemplateLiteral(node, context);
1455
- }
1456
- async evaluateSimpleExpression(exprCode, context) {
1457
- return evaluateSimpleExpression(exprCode, context);
1458
- }
1459
- async resolveValue(name, context) {
1460
- return resolveValue(name, context);
1461
- }
1462
- async evaluateIdentifier(node, context) {
1463
- const { name, scope } = node;
1464
- if (name === 'me' || name === 'my' || name === 'I') {
1465
- return context.me;
1466
- }
1467
- if (name === 'you' || name === 'your') {
1468
- return context.you;
1469
- }
1470
- if (name === 'it' || name === 'its') {
1471
- return context.it;
1472
- }
1473
- if (name === 'result') {
1474
- return context.result;
1475
- }
1476
- if (name === 'event') {
1477
- return context.event;
1478
- }
1479
- const expression = this.expressionRegistry.get(name);
1480
- if (expression) {
1481
- return expression.evaluate(context);
1482
- }
1483
- if (scope === 'local') {
1484
- if (context.locals?.has(name)) {
1485
- return context.locals.get(name);
1486
- }
1487
- return undefined;
1488
- }
1489
- if (scope === 'global') {
1490
- if (context.globals?.has(name)) {
1491
- return context.globals.get(name);
1492
- }
1493
- if (typeof window !== 'undefined' && name in window) {
1494
- return window[name];
1495
- }
1496
- return undefined;
1497
- }
1498
- if (context.locals?.has(name)) {
1499
- return context.locals.get(name);
1500
- }
1501
- if (context.globals?.has(name)) {
1502
- return context.globals.get(name);
1503
- }
1504
- if (context.variables?.has(name)) {
1505
- return context.variables.get(name);
1506
- }
1507
- if (typeof globalThis !== 'undefined' && name in globalThis) {
1508
- return globalThis[name];
1509
- }
1510
- if (typeof window !== 'undefined' && name in window) {
1511
- return window[name];
1512
- }
1513
- return undefined;
1514
- }
1515
- async evaluateLiteral(node, _context) {
1516
- return node.value;
1517
- }
1518
- async evaluateContextReference(node, context) {
1519
- const { contextType } = node;
1520
- switch (contextType) {
1521
- case 'me':
1522
- return context.me;
1523
- case 'it':
1524
- return context.result;
1525
- case 'you':
1526
- return context.you;
1527
- case 'event':
1528
- return context.event;
1529
- case 'body':
1530
- return (context.meta?.ownerDocument?.body || document?.body);
1531
- case 'detail':
1532
- return context.event?.detail;
1533
- case 'target':
1534
- return context.you || context.event?.target;
1535
- case 'sender':
1536
- return context.event?.target;
1537
- default:
1538
- if (context.locals && context.locals.has(contextType)) {
1539
- return context.locals.get(contextType);
1540
- }
1541
- debug.expressions(`Unknown context reference type: ${contextType}`);
1542
- return undefined;
1543
- }
1544
- }
1545
- async evaluateMemberExpression(node, context) {
1546
- const { object, property, computed } = node;
1547
- if (object.type === 'identifier' && ['add', 'remove'].includes(object.name)) {
1548
- const commandName = object.name;
1549
- const className = extractPropertyName(property);
1550
- if (!context.me) {
1551
- throw new Error('Context element "me" is null');
1552
- }
1553
- if (commandName === 'add') {
1554
- context.me.classList.add(className);
1555
- }
1556
- else if (commandName === 'remove') {
1557
- context.me.classList.remove(className);
1558
- }
1559
- return;
1560
- }
1561
- let objectValue = await this.evaluate(object, context);
1562
- if (computed) {
1563
- const propertyValue = await this.evaluate(property, context);
1564
- return objectValue[propertyValue];
1565
- }
1566
- else {
1567
- const propertyName = extractPropertyName(property);
1568
- const isArrayProp = Array.isArray(objectValue) &&
1569
- typeof propertyName === 'string' &&
1570
- (propertyName === 'length' || propertyName in Array.prototype);
1571
- if (!isArrayProp) {
1572
- objectValue = this.unwrapSelectorResult(objectValue);
1573
- }
1574
- if (typeof propertyName === 'string') {
1575
- if (propertyName.startsWith('computed-')) {
1576
- const styleProp = propertyName.substring('computed-'.length);
1577
- if (objectValue && typeof window !== 'undefined' && objectValue instanceof Element) {
1578
- const computedStyle = window.getComputedStyle(objectValue);
1579
- return computedStyle.getPropertyValue(styleProp);
1580
- }
1581
- return undefined;
1582
- }
1583
- if (propertyName.startsWith('@')) {
1584
- const attrName = propertyName.substring(1);
1585
- if (objectValue && typeof objectValue.getAttribute === 'function') {
1586
- return accessAttribute(objectValue, attrName);
1587
- }
1588
- return undefined;
1589
- }
1590
- if (objectValue && objectValue instanceof Element) {
1591
- if (propertyName === 'previous' || propertyName === 'prev') {
1592
- return objectValue.previousElementSibling;
1593
- }
1594
- if (propertyName === 'next') {
1595
- return objectValue.nextElementSibling;
1596
- }
1597
- }
1598
- }
1599
- const value = objectValue?.[propertyName];
1600
- if (typeof value === 'function') {
1601
- return value.bind(objectValue);
1602
- }
1603
- return value;
1604
- }
1605
- }
1606
- coerceArithmeticOperand(value) {
1607
- return coerceArithmeticOperand(value);
1608
- }
1609
- async evaluateBinaryExpression(node, context) {
1610
- return evaluateBinaryExpression(node, context, this.evaluate.bind(this), this.unwrapSelectorResult.bind(this), this.expressionRegistry, this.evaluateSelector.bind(this));
1611
- }
1612
- async evaluateUnaryExpression(node, context) {
1613
- const { operator, argument } = node;
1614
- const operandValue = await this.evaluate(argument, context);
1615
- switch (operator) {
1616
- case 'not':
1617
- case '!':
1618
- const notExpr = this.expressionRegistry.get('not');
1619
- return notExpr ? notExpr.evaluate(context, operandValue) : !operandValue;
1620
- case 'no':
1621
- const noExpr = this.expressionRegistry.get('no');
1622
- return noExpr ? noExpr.evaluate(context, operandValue) : false;
1623
- case 'some':
1624
- if (operandValue === null || operandValue === undefined)
1625
- return false;
1626
- if (typeof operandValue === 'string')
1627
- return operandValue.length > 0;
1628
- if (Array.isArray(operandValue))
1629
- return operandValue.length > 0;
1630
- if (operandValue instanceof NodeList)
1631
- return operandValue.length > 0;
1632
- if (operandValue instanceof HTMLCollection)
1633
- return operandValue.length > 0;
1634
- if (typeof operandValue === 'object')
1635
- return Object.keys(operandValue).length > 0;
1636
- return true;
1637
- case 'exists':
1638
- const existsExpr = this.expressionRegistry.get('exists');
1639
- return existsExpr ? existsExpr.evaluate(context, operandValue) : operandValue != null;
1640
- case 'does not exist':
1641
- const doesNotExistExpr = this.expressionRegistry.get('doesNotExist');
1642
- return doesNotExistExpr
1643
- ? doesNotExistExpr.evaluate(context, operandValue)
1644
- : operandValue == null;
1645
- case '-':
1646
- return -operandValue;
1647
- case '+':
1648
- return +operandValue;
1649
- default:
1650
- throw new Error(`Unsupported unary operator: ${operator}`);
1651
- }
1652
- }
1653
- async evaluateCallExpression(node, context) {
1654
- return evaluateCallExpression(node, context, this.evaluate.bind(this), this.unwrapSelectorResult.bind(this), this.expressionRegistry, this.evaluateSelector.bind(this));
1655
- }
1656
- async evaluateMethodCall(callee, args, context) {
1657
- return evaluateMethodCall(callee, args, context, this.evaluate.bind(this), this.unwrapSelectorResult.bind(this));
1658
- }
1659
- async evaluateSelector(node, context) {
1660
- return evaluateSelector(node, context);
1661
- }
1662
- evaluateAttributeAccess(node, context) {
1663
- if (context.me && typeof context.me.getAttribute === 'function') {
1664
- return accessAttribute(context.me, node.attributeName);
1665
- }
1666
- return `@${node.attributeName}`;
1667
- }
1668
- async evaluateAsExpression(node, context) {
1669
- const value = await this.evaluate(node.expression, context);
1670
- const asExpr = this.expressionRegistry.get('as');
1671
- if (asExpr) {
1672
- return asExpr.evaluate(context, value, node.targetType);
1673
- }
1674
- throw new Error(`Conversion type 'as' not registered`);
1675
- }
1676
- getAvailableExpressions() {
1677
- return Array.from(this.expressionRegistry.keys());
1678
- }
1679
- async evaluateDollarExpression(node, context) {
1680
- const value = await this.evaluate(node.expression, context);
1681
- if (node.expression.type === 'identifier') {
1682
- const varName = node.expression.name;
1683
- if (/^\d+$/.test(varName)) {
1684
- return varName;
1685
- }
1686
- if (context.locals?.has(varName)) {
1687
- return context.locals.get(varName);
1688
- }
1689
- if (varName === 'me' && context.me)
1690
- return context.me;
1691
- if (varName === 'you' && context.you)
1692
- return context.you;
1693
- if (varName === 'it' && context.it)
1694
- return context.it;
1695
- if (varName === 'result' && context.result)
1696
- return context.result;
1697
- if (typeof window !== 'undefined' && varName === 'window') {
1698
- return window;
1699
- }
1700
- if (context.globals?.has(varName)) {
1701
- return context.globals.get(varName);
1702
- }
1703
- return undefined;
1704
- }
1705
- return value;
1706
- }
1707
- async evaluatePossessiveExpression(node, context) {
1708
- const { object, property } = node;
1709
- const objectValue = this.unwrapSelectorResult(await this.evaluate(object, context));
1710
- if (!objectValue) {
1711
- return undefined;
1712
- }
1713
- const propertyName = extractPropertyName(property);
1714
- if (typeof propertyName === 'string') {
1715
- if (isElement(objectValue)) {
1716
- return getElementProperty(objectValue, propertyName);
1717
- }
1718
- return objectValue[propertyName];
1719
- }
1720
- return objectValue[propertyName];
1721
- }
1722
- hasExpression(name) {
1723
- return this.expressionRegistry.has(name);
1724
- }
1725
- async evaluateCSSSelector(node, context) {
1726
- return evaluateCSSSelector(node, context);
1727
- }
1728
- async evaluateIdSelector(node, context) {
1729
- return evaluateIdSelector(node, context);
1730
- }
1731
- async evaluateQueryReference(node, context) {
1732
- return evaluateQueryReference(node, context);
1733
- }
1734
- async evaluatePropertyAccess(node, context) {
1735
- const object = await this.evaluate(node.object, context);
1736
- const propertyNode = node.property;
1737
- if (object === null || object === undefined) {
1738
- throw new Error(`Cannot access property "${propertyNode.name || propertyNode.value}" of ${object}`);
1739
- }
1740
- const propertyName = propertyNode.name || propertyNode.value;
1741
- if (!propertyName) {
1742
- throw new Error('Property name must be an identifier');
1743
- }
1744
- try {
1745
- let value;
1746
- if (isElement(object)) {
1747
- value = getElementProperty(object, propertyName);
1748
- }
1749
- else {
1750
- value = object[propertyName];
1751
- }
1752
- if (typeof value === 'function') {
1753
- return value.bind(object);
1754
- }
1755
- return value;
1756
- }
1757
- catch (error) {
1758
- throw new Error(`Error accessing property "${propertyName}": ${error}`);
1759
- }
1760
- }
1761
- async evaluatePropertyOfExpression(node, context) {
1762
- const propertyNode = node.property;
1763
- const propertyName = propertyNode.name || propertyNode.value;
1764
- if (!propertyName) {
1765
- throw new Error('Property name must be an identifier in "the X of Y" pattern');
1766
- }
1767
- const target = this.unwrapSelectorResult(await this.evaluate(node.target, context));
1768
- if (target === null || target === undefined) {
1769
- throw new Error(`Cannot access property "${propertyName}" of ${target}`);
1770
- }
1771
- try {
1772
- let value;
1773
- if (isElement(target)) {
1774
- value = getElementProperty(target, propertyName);
1775
- }
1776
- else {
1777
- value = target[propertyName];
1778
- }
1779
- if (typeof value === 'function') {
1780
- return value.bind(target);
1781
- }
1782
- return value;
1783
- }
1784
- catch (error) {
1785
- throw new Error(`Failed to access property "${propertyName}" on target: ${error}`);
1786
- }
264
+ coerceFrom: {
265
+ String: v => {
266
+ try {
267
+ const parsed = JSON.parse(v);
268
+ if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
269
+ return parsed;
270
+ }
271
+ }
272
+ catch {
273
+ }
274
+ return null;
275
+ },
276
+ Array: v => {
277
+ const arr = v;
278
+ const obj = {};
279
+ arr.forEach((item, index) => {
280
+ obj[String(index)] = item;
281
+ });
282
+ return obj;
283
+ },
284
+ },
285
+ });
286
+ this.register({
287
+ name: 'Null',
288
+ hyperscriptType: 'null',
289
+ tsType: 'null',
290
+ isType: (v) => v === null,
291
+ defaultValue: null,
292
+ description: 'Null value',
293
+ });
294
+ this.register({
295
+ name: 'Undefined',
296
+ hyperscriptType: 'undefined',
297
+ tsType: 'undefined',
298
+ isType: (v) => v === undefined,
299
+ defaultValue: undefined,
300
+ description: 'Undefined value',
301
+ });
302
+ this.register({
303
+ name: 'Function',
304
+ hyperscriptType: 'function',
305
+ tsType: 'Function',
306
+ isType: (v) => typeof v === 'function',
307
+ defaultValue: null,
308
+ description: 'JavaScript function',
309
+ });
310
+ this.register({
311
+ name: 'Event',
312
+ hyperscriptType: 'event',
313
+ tsType: 'Event',
314
+ isType: (v) => v instanceof Event,
315
+ defaultValue: null,
316
+ description: 'DOM Event',
317
+ });
318
+ this.register({
319
+ name: 'NodeList',
320
+ hyperscriptType: 'element-list',
321
+ tsType: 'NodeList',
322
+ isType: (v) => v instanceof NodeList,
323
+ defaultValue: null,
324
+ description: 'DOM NodeList (typically from querySelectorAll)',
325
+ coerceFrom: {
326
+ Array: v => {
327
+ return null;
328
+ },
329
+ },
330
+ });
331
+ this.register({
332
+ name: 'Unknown',
333
+ hyperscriptType: 'unknown',
334
+ tsType: 'unknown',
335
+ isType: (_v) => true,
336
+ defaultValue: null,
337
+ description: 'Unknown/any value type',
338
+ });
1787
339
  }
1788
340
  }
341
+ const expressionTypeRegistry = new ExpressionTypeRegistry();
1789
342
 
1790
- class ConfigurableExpressionEvaluator extends BaseExpressionEvaluator {
1791
- constructor(categories) {
1792
- super();
1793
- for (const category of categories) {
1794
- this.registerCategory(category);
1795
- }
1796
- }
343
+ function isString(value) {
344
+ const stringType = expressionTypeRegistry.get('String');
345
+ return stringType ? stringType.isType(value) : typeof value === 'string';
346
+ }
347
+ function isNumber(value) {
348
+ const numberType = expressionTypeRegistry.get('Number');
349
+ return numberType ? numberType.isType(value) : typeof value === 'number';
350
+ }
351
+ function isBoolean(value) {
352
+ const boolType = expressionTypeRegistry.get('Boolean');
353
+ return boolType ? boolType.isType(value) : typeof value === 'boolean';
354
+ }
355
+ function isObject(value) {
356
+ const objectType = expressionTypeRegistry.get('Object');
357
+ return objectType ? objectType.isType(value) : typeof value === 'object' && value !== null;
358
+ }
359
+ function isFunction(value) {
360
+ const funcType = expressionTypeRegistry.get('Function');
361
+ return funcType ? funcType.isType(value) : typeof value === 'function';
1797
362
  }
1798
363
 
1799
364
  const NUMBER_WORDS = {
@@ -2744,7 +1309,7 @@ const meExpression = {
2744
1309
  category: 'Reference',
2745
1310
  evaluatesTo: 'Element',
2746
1311
  async evaluate(context) {
2747
- return context.me instanceof HTMLElement ? context.me : null;
1312
+ return context.me ?? null;
2748
1313
  },
2749
1314
  validate: validateNoArgs,
2750
1315
  };
@@ -2753,7 +1318,7 @@ const youExpression = {
2753
1318
  category: 'Reference',
2754
1319
  evaluatesTo: 'Element',
2755
1320
  async evaluate(context) {
2756
- return context.you instanceof HTMLElement ? context.you : null;
1321
+ return context.you ?? null;
2757
1322
  },
2758
1323
  validate: validateNoArgs,
2759
1324
  };
@@ -3432,6 +1997,39 @@ function toNumberOrNull(value) {
3432
1997
  }
3433
1998
  return null;
3434
1999
  }
2000
+ function ensureFinite(num, operation) {
2001
+ if (!Number.isFinite(num)) {
2002
+ if (Number.isNaN(num)) {
2003
+ throw new Error(`${operation} resulted in non-finite value: NaN`);
2004
+ }
2005
+ throw new Error(`${operation} resulted in non-finite value: ${num > 0 ? 'Infinity' : '-Infinity'}`);
2006
+ }
2007
+ return num;
2008
+ }
2009
+ function canBeNumeric(value) {
2010
+ try {
2011
+ toNumber(value, '_');
2012
+ return true;
2013
+ }
2014
+ catch {
2015
+ return false;
2016
+ }
2017
+ }
2018
+ function safeDivide(left, right, allowInfinity = true) {
2019
+ if (right === 0) {
2020
+ if (allowInfinity) {
2021
+ return left === 0 ? NaN : left > 0 ? Infinity : -Infinity;
2022
+ }
2023
+ throw new Error('Division by zero');
2024
+ }
2025
+ return left / right;
2026
+ }
2027
+ function safeModulo(left, right) {
2028
+ if (right === 0) {
2029
+ throw new Error('Modulo by zero');
2030
+ }
2031
+ return left % right;
2032
+ }
3435
2033
 
3436
2034
  function compareValues(left, right, operator) {
3437
2035
  if (operator === '===') {
@@ -3541,6 +2139,44 @@ function coerceToComparable(left, right) {
3541
2139
  return [String(left), String(right)];
3542
2140
  }
3543
2141
 
2142
+ function validResult() {
2143
+ return {
2144
+ isValid: true,
2145
+ errors: [],
2146
+ suggestions: [],
2147
+ };
2148
+ }
2149
+ function invalidResult(errors, suggestions = []) {
2150
+ return {
2151
+ isValid: false,
2152
+ errors,
2153
+ suggestions,
2154
+ };
2155
+ }
2156
+ function createError(type, message, suggestions = [], severity = 'error') {
2157
+ return { type, message, suggestions, severity };
2158
+ }
2159
+ function validateBinaryInput(input) {
2160
+ if (input === null || input === undefined) {
2161
+ return invalidResult([createError('missing-argument', 'Input is null or undefined')], ['Provide an object with left and right operands']);
2162
+ }
2163
+ if (typeof input !== 'object') {
2164
+ return invalidResult([createError('type-mismatch', `Expected object, got ${typeof input}`)], ['Provide an object with left and right operands']);
2165
+ }
2166
+ const obj = input;
2167
+ if (!('left' in obj) || !('right' in obj)) {
2168
+ const missing = [];
2169
+ if (!('left' in obj))
2170
+ missing.push('left');
2171
+ if (!('right' in obj))
2172
+ missing.push('right');
2173
+ return invalidResult([
2174
+ createError('missing-argument', `Missing ${missing.join(' and ')} operand${missing.length > 1 ? 's' : ''}`),
2175
+ ], ['Provide { left: value, right: value }']);
2176
+ }
2177
+ return validResult();
2178
+ }
2179
+
3544
2180
  function trackEvaluation(expression, context, args, result, startTime, success = true, error) {
3545
2181
  if (context &&
3546
2182
  typeof context === 'object' &&
@@ -4189,10 +2825,6 @@ const noExpression = {
4189
2825
  result = value.length === 0;
4190
2826
  else if (isString(value))
4191
2827
  result = false;
4192
- else if (value instanceof Node || value instanceof Element)
4193
- result = false;
4194
- else if (isObject(value))
4195
- result = Object.keys(value).length === 0;
4196
2828
  else
4197
2829
  result = false;
4198
2830
  if (tracking)
@@ -4368,6 +3000,33 @@ const endsWithExpression = {
4368
3000
  return validateArgCount(args, 2, 'endsWith', 'str, suffix');
4369
3001
  },
4370
3002
  };
3003
+ const betweenExpression = {
3004
+ name: 'between',
3005
+ category: 'Logical',
3006
+ evaluatesTo: 'Boolean',
3007
+ operators: ['is between', 'between'],
3008
+ async evaluate(context, value, min, max) {
3009
+ const tracking = context.evaluationHistory;
3010
+ const startTime = tracking ? Date.now() : 0;
3011
+ let lo = min;
3012
+ let hi = max;
3013
+ if (lo != null && hi != null && lo > hi) {
3014
+ const swap = lo;
3015
+ lo = hi;
3016
+ hi = swap;
3017
+ }
3018
+ const result = lo != null &&
3019
+ hi != null &&
3020
+ value >= lo &&
3021
+ value <= hi;
3022
+ if (tracking)
3023
+ trackEvaluation(this, context, [value, min, max], result, startTime);
3024
+ return result;
3025
+ },
3026
+ validate(args) {
3027
+ return validateArgCount(args, 3, 'between', 'value, min, max');
3028
+ },
3029
+ };
4371
3030
  const matchesExpression = {
4372
3031
  name: 'matches',
4373
3032
  category: 'Logical',
@@ -4564,11 +3223,438 @@ const logicalExpressions = {
4564
3223
  doesNotContain: doesNotContainExpression,
4565
3224
  startsWith: startsWithExpression,
4566
3225
  endsWith: endsWithExpression,
3226
+ between: betweenExpression,
4567
3227
  matches: matchesExpression,
4568
3228
  has: hasExpression,
4569
3229
  doesNotHave: doesNotHaveExpression,
4570
3230
  };
4571
3231
 
3232
+ function mergeFragments(...fragments) {
3233
+ const merged = new Map();
3234
+ for (const fragment of fragments) {
3235
+ for (const [key, entry] of fragment) {
3236
+ const existing = merged.get(key);
3237
+ if (existing) {
3238
+ merged.set(key, {
3239
+ prefix: entry.prefix ?? existing.prefix,
3240
+ infix: entry.infix ?? existing.infix,
3241
+ });
3242
+ }
3243
+ else {
3244
+ merged.set(key, { ...entry });
3245
+ }
3246
+ }
3247
+ }
3248
+ return merged;
3249
+ }
3250
+ function leftAssoc(bp, handler) {
3251
+ return {
3252
+ infix: {
3253
+ bp: [bp, bp + 1],
3254
+ handler: handler ??
3255
+ ((left, token, ctx) => {
3256
+ const right = ctx.parseExpr(bp + 1);
3257
+ return {
3258
+ type: 'binaryExpression',
3259
+ operator: token.value,
3260
+ left,
3261
+ right,
3262
+ start: left.start,
3263
+ end: right.end ?? token.end,
3264
+ line: left.line ?? token.line,
3265
+ column: left.column ?? token.column,
3266
+ };
3267
+ }),
3268
+ },
3269
+ };
3270
+ }
3271
+ function rightAssoc(bp, handler) {
3272
+ return {
3273
+ infix: {
3274
+ bp: [bp + 1, bp],
3275
+ handler: ((left, token, ctx) => {
3276
+ const right = ctx.parseExpr(bp);
3277
+ return {
3278
+ type: 'binaryExpression',
3279
+ operator: token.value,
3280
+ left,
3281
+ right,
3282
+ start: left.start,
3283
+ end: right.end ?? token.end,
3284
+ line: left.line ?? token.line,
3285
+ column: left.column ?? token.column,
3286
+ };
3287
+ }),
3288
+ },
3289
+ };
3290
+ }
3291
+ function prefix(bp, handler) {
3292
+ return {
3293
+ prefix: {
3294
+ bp,
3295
+ handler: handler ??
3296
+ ((token, ctx) => {
3297
+ const operand = ctx.parseExpr(bp);
3298
+ return {
3299
+ type: 'unaryExpression',
3300
+ operator: token.value,
3301
+ operand,
3302
+ argument: operand,
3303
+ prefix: true,
3304
+ start: token.start,
3305
+ end: operand.end ?? token.end,
3306
+ line: token.line,
3307
+ column: token.column,
3308
+ };
3309
+ }),
3310
+ },
3311
+ };
3312
+ }
3313
+ const CORE_FRAGMENT = new Map([
3314
+ ['or', leftAssoc(10)],
3315
+ ['||', leftAssoc(10)],
3316
+ ['and', leftAssoc(20)],
3317
+ ['&&', leftAssoc(20)],
3318
+ ['==', leftAssoc(30)],
3319
+ ['!=', leftAssoc(30)],
3320
+ ['<', leftAssoc(30)],
3321
+ ['>', leftAssoc(30)],
3322
+ ['<=', leftAssoc(30)],
3323
+ ['>=', leftAssoc(30)],
3324
+ ['is', leftAssoc(30)],
3325
+ ['matches', leftAssoc(30)],
3326
+ ['contains', leftAssoc(30)],
3327
+ ['starts with', leftAssoc(30)],
3328
+ ['ends with', leftAssoc(30)],
3329
+ ['does not start with', leftAssoc(30)],
3330
+ ['does not end with', leftAssoc(30)],
3331
+ [
3332
+ 'is between',
3333
+ leftAssoc(30, (left, _token, ctx) => {
3334
+ const min = ctx.parseExpr(31);
3335
+ const next = ctx.peek();
3336
+ if (!next || next.value.toLowerCase() !== 'and') {
3337
+ throw new Error(`between requires 'and' between min and max operands, got: ${next?.value ?? '<end>'}`);
3338
+ }
3339
+ ctx.advance();
3340
+ const max = ctx.parseExpr(31);
3341
+ return {
3342
+ type: 'betweenExpression',
3343
+ value: left,
3344
+ min,
3345
+ max,
3346
+ negated: false,
3347
+ start: left.start,
3348
+ end: max.end,
3349
+ };
3350
+ }),
3351
+ ],
3352
+ [
3353
+ 'is not between',
3354
+ leftAssoc(30, (left, _token, ctx) => {
3355
+ const min = ctx.parseExpr(31);
3356
+ const next = ctx.peek();
3357
+ if (!next || next.value.toLowerCase() !== 'and') {
3358
+ throw new Error(`between requires 'and' between min and max operands, got: ${next?.value ?? '<end>'}`);
3359
+ }
3360
+ ctx.advance();
3361
+ const max = ctx.parseExpr(31);
3362
+ return {
3363
+ type: 'betweenExpression',
3364
+ value: left,
3365
+ min,
3366
+ max,
3367
+ negated: true,
3368
+ start: left.start,
3369
+ end: max.end,
3370
+ };
3371
+ }),
3372
+ ],
3373
+ [
3374
+ 'ignoring case',
3375
+ {
3376
+ infix: {
3377
+ bp: [25, 26],
3378
+ handler: (left, _token, _ctx) => {
3379
+ left.ignoringCase = true;
3380
+ return left;
3381
+ },
3382
+ },
3383
+ },
3384
+ ],
3385
+ [
3386
+ 'where',
3387
+ leftAssoc(28, (left, _token, ctx) => {
3388
+ const predicate = ctx.parseExpr(29);
3389
+ return {
3390
+ type: 'collectionExpression',
3391
+ operator: 'where',
3392
+ collection: left,
3393
+ right: predicate,
3394
+ start: left.start,
3395
+ end: predicate.end,
3396
+ };
3397
+ }),
3398
+ ],
3399
+ [
3400
+ 'sorted by',
3401
+ leftAssoc(28, (left, _token, ctx) => {
3402
+ const keyExpr = ctx.parseExpr(29);
3403
+ let order = 'asc';
3404
+ const next = ctx.peek();
3405
+ if (next && typeof next.value === 'string') {
3406
+ const v = next.value.toLowerCase();
3407
+ if (v === 'asc' || v === 'ascending') {
3408
+ ctx.advance();
3409
+ order = 'asc';
3410
+ }
3411
+ else if (v === 'desc' || v === 'descending') {
3412
+ ctx.advance();
3413
+ order = 'desc';
3414
+ }
3415
+ }
3416
+ return {
3417
+ type: 'collectionExpression',
3418
+ operator: 'sorted by',
3419
+ collection: left,
3420
+ right: keyExpr,
3421
+ order,
3422
+ start: left.start,
3423
+ end: keyExpr.end,
3424
+ };
3425
+ }),
3426
+ ],
3427
+ [
3428
+ 'mapped to',
3429
+ leftAssoc(28, (left, _token, ctx) => {
3430
+ const expr = ctx.parseExpr(29);
3431
+ return {
3432
+ type: 'collectionExpression',
3433
+ operator: 'mapped to',
3434
+ collection: left,
3435
+ right: expr,
3436
+ start: left.start,
3437
+ end: expr.end,
3438
+ };
3439
+ }),
3440
+ ],
3441
+ [
3442
+ 'split by',
3443
+ leftAssoc(28, (left, _token, ctx) => {
3444
+ const sep = ctx.parseExpr(29);
3445
+ return {
3446
+ type: 'collectionExpression',
3447
+ operator: 'split by',
3448
+ collection: left,
3449
+ right: sep,
3450
+ start: left.start,
3451
+ end: sep.end,
3452
+ };
3453
+ }),
3454
+ ],
3455
+ [
3456
+ 'joined by',
3457
+ leftAssoc(28, (left, _token, ctx) => {
3458
+ const sep = ctx.parseExpr(29);
3459
+ return {
3460
+ type: 'collectionExpression',
3461
+ operator: 'joined by',
3462
+ collection: left,
3463
+ right: sep,
3464
+ start: left.start,
3465
+ end: sep.end,
3466
+ };
3467
+ }),
3468
+ ],
3469
+ ['+', { ...leftAssoc(40), ...prefix(80) }],
3470
+ ['-', { ...leftAssoc(40), ...prefix(80) }],
3471
+ ['*', leftAssoc(50)],
3472
+ ['/', leftAssoc(50)],
3473
+ ['%', leftAssoc(50)],
3474
+ ['mod', leftAssoc(50)],
3475
+ ['^', rightAssoc(60)],
3476
+ ['**', rightAssoc(60)],
3477
+ [
3478
+ 'as',
3479
+ leftAssoc(70, (left, token, ctx) => {
3480
+ const targetType = ctx.parseExpr(71);
3481
+ const peeked = ctx.peek();
3482
+ if (peeked &&
3483
+ peeked.value === ':' &&
3484
+ targetType &&
3485
+ targetType.type === 'identifier') {
3486
+ ctx.advance();
3487
+ const suffix = ctx.advance();
3488
+ if (suffix && suffix.value !== undefined) {
3489
+ targetType.name = `${targetType.name}:${suffix.value}`;
3490
+ targetType.end = suffix.end;
3491
+ }
3492
+ }
3493
+ return {
3494
+ type: 'asExpression',
3495
+ expression: left,
3496
+ targetType,
3497
+ start: left.start,
3498
+ end: targetType.end ?? token.end,
3499
+ line: left.line ?? token.line,
3500
+ column: left.column ?? token.column,
3501
+ };
3502
+ }),
3503
+ ],
3504
+ ['not', prefix(80)],
3505
+ ['!', prefix(80)],
3506
+ ['no', prefix(80)],
3507
+ ]);
3508
+ function makeTypeCheckHandler(negated) {
3509
+ return (left, _token, ctx) => {
3510
+ const typeToken = ctx.advance();
3511
+ if (!typeToken || !typeToken.value) {
3512
+ throw new Error(`Type check requires a type name after 'is ${negated ? 'not ' : ''}a/an', got: <end>`);
3513
+ }
3514
+ let nullOk = true;
3515
+ const peeked = ctx.peek();
3516
+ if (peeked && peeked.value === '!') {
3517
+ ctx.advance();
3518
+ nullOk = false;
3519
+ }
3520
+ return {
3521
+ type: 'typeCheckExpression',
3522
+ value: left,
3523
+ typeName: typeToken.value,
3524
+ nullOk,
3525
+ negated,
3526
+ start: left.start,
3527
+ end: typeToken.end,
3528
+ };
3529
+ };
3530
+ }
3531
+ const PARSER_COMPARISON_FRAGMENT = new Map([
3532
+ ['===', leftAssoc(30)],
3533
+ ['!==', leftAssoc(30)],
3534
+ ['is not', leftAssoc(30)],
3535
+ ['am', leftAssoc(30)],
3536
+ ['is in', leftAssoc(30)],
3537
+ ['is not in', leftAssoc(30)],
3538
+ ['precedes', leftAssoc(30)],
3539
+ ['does not precede', leftAssoc(30)],
3540
+ ['follows', leftAssoc(30)],
3541
+ ['does not follow', leftAssoc(30)],
3542
+ ['is a', leftAssoc(30, makeTypeCheckHandler(false))],
3543
+ ['is an', leftAssoc(30, makeTypeCheckHandler(false))],
3544
+ ['is not a', leftAssoc(30, makeTypeCheckHandler(true))],
3545
+ ['is not an', leftAssoc(30, makeTypeCheckHandler(true))],
3546
+ ['has', leftAssoc(30)],
3547
+ ['have', leftAssoc(30)],
3548
+ ['match', leftAssoc(30)],
3549
+ ['include', leftAssoc(30)],
3550
+ ['includes', leftAssoc(30)],
3551
+ ['equals', leftAssoc(30)],
3552
+ ['does not contain', leftAssoc(30)],
3553
+ ['does not include', leftAssoc(30)],
3554
+ ['is equal to', leftAssoc(30)],
3555
+ ['is not equal to', leftAssoc(30)],
3556
+ ['is really equal to', leftAssoc(30)],
3557
+ ['is not really equal to', leftAssoc(30)],
3558
+ ['really equals', leftAssoc(30)],
3559
+ ['is greater than', leftAssoc(30)],
3560
+ ['is less than', leftAssoc(30)],
3561
+ ['is greater than or equal to', leftAssoc(30)],
3562
+ ['is less than or equal to', leftAssoc(30)],
3563
+ ['in', leftAssoc(30)],
3564
+ ['of', leftAssoc(30)],
3565
+ ['really', leftAssoc(30)],
3566
+ [
3567
+ 'exists',
3568
+ {
3569
+ prefix: {
3570
+ bp: 80,
3571
+ handler: (token, ctx) => ({
3572
+ type: 'unaryExpression',
3573
+ operator: token.value,
3574
+ operand: ctx.parseExpr(80),
3575
+ start: token.start,
3576
+ }),
3577
+ },
3578
+ infix: {
3579
+ bp: [30, 31],
3580
+ handler: (left, token) => ({
3581
+ type: 'unaryExpression',
3582
+ operator: token.value,
3583
+ operand: left,
3584
+ prefix: false,
3585
+ start: left.start,
3586
+ }),
3587
+ },
3588
+ },
3589
+ ],
3590
+ [
3591
+ 'does not exist',
3592
+ {
3593
+ infix: {
3594
+ bp: [30, 31],
3595
+ handler: (left, token) => ({
3596
+ type: 'unaryExpression',
3597
+ operator: token.value,
3598
+ operand: left,
3599
+ prefix: false,
3600
+ start: left.start,
3601
+ }),
3602
+ },
3603
+ },
3604
+ ],
3605
+ [
3606
+ 'is empty',
3607
+ {
3608
+ infix: {
3609
+ bp: [30, 31],
3610
+ handler: (left, token) => ({
3611
+ type: 'unaryExpression',
3612
+ operator: token.value,
3613
+ operand: left,
3614
+ prefix: false,
3615
+ start: left.start,
3616
+ }),
3617
+ },
3618
+ },
3619
+ ],
3620
+ [
3621
+ 'is not empty',
3622
+ {
3623
+ infix: {
3624
+ bp: [30, 31],
3625
+ handler: (left, token) => ({
3626
+ type: 'unaryExpression',
3627
+ operator: token.value,
3628
+ operand: left,
3629
+ prefix: false,
3630
+ start: left.start,
3631
+ }),
3632
+ },
3633
+ },
3634
+ ],
3635
+ ['some', prefix(80)],
3636
+ ]);
3637
+ const ASSIGNMENT_FRAGMENT = new Map([
3638
+ ['=', rightAssoc(5)],
3639
+ ]);
3640
+ mergeFragments(CORE_FRAGMENT, PARSER_COMPARISON_FRAGMENT, ASSIGNMENT_FRAGMENT);
3641
+
3642
+ const LOCAL_READ_HOOKS = new Set();
3643
+ function notifyLocalRead(name, context) {
3644
+ if (LOCAL_READ_HOOKS.size === 0)
3645
+ return;
3646
+ for (const hook of LOCAL_READ_HOOKS) {
3647
+ try {
3648
+ hook(name, context);
3649
+ }
3650
+ catch (err) {
3651
+ if (typeof console !== 'undefined') {
3652
+ console.error('[hyperfixi] localReadHook threw:', err);
3653
+ }
3654
+ }
3655
+ }
3656
+ }
3657
+
4572
3658
  const StringLiteralInputSchema = v
4573
3659
  .object({
4574
3660
  value: v.string().describe('String literal value'),
@@ -4682,6 +3768,7 @@ class StringLiteralExpression extends BaseExpressionImpl {
4682
3768
  if (varName === 'result' && context.result)
4683
3769
  return context.result;
4684
3770
  if (context.locals?.has(varName)) {
3771
+ notifyLocalRead(varName, context);
4685
3772
  return context.locals.get(varName);
4686
3773
  }
4687
3774
  if (context.globals?.has(varName)) {
@@ -4791,7 +3878,7 @@ class BooleanLiteralExpression extends BaseExpressionImpl {
4791
3878
  }
4792
3879
  }
4793
3880
  }
4794
- class AdditionExpression extends BaseExpressionImpl {
3881
+ let AdditionExpression$1 = class AdditionExpression extends BaseExpressionImpl {
4795
3882
  constructor() {
4796
3883
  super(...arguments);
4797
3884
  this.name = 'addition';
@@ -4838,7 +3925,7 @@ class AdditionExpression extends BaseExpressionImpl {
4838
3925
  ]);
4839
3926
  }
4840
3927
  }
4841
- }
3928
+ };
4842
3929
  class StringConcatenationExpression extends BaseExpressionImpl {
4843
3930
  constructor() {
4844
3931
  super(...arguments);
@@ -4901,7 +3988,7 @@ class StringConcatenationExpression extends BaseExpressionImpl {
4901
3988
  }
4902
3989
  }
4903
3990
  }
4904
- class MultiplicationExpression extends BaseExpressionImpl {
3991
+ let MultiplicationExpression$1 = class MultiplicationExpression extends BaseExpressionImpl {
4905
3992
  constructor() {
4906
3993
  super(...arguments);
4907
3994
  this.name = 'multiplication';
@@ -4948,7 +4035,7 @@ class MultiplicationExpression extends BaseExpressionImpl {
4948
4035
  ]);
4949
4036
  }
4950
4037
  }
4951
- }
4038
+ };
4952
4039
  function createStringLiteralExpression() {
4953
4040
  return new StringLiteralExpression();
4954
4041
  }
@@ -4958,30 +4045,26 @@ function createNumberLiteralExpression() {
4958
4045
  function createBooleanLiteralExpression() {
4959
4046
  return new BooleanLiteralExpression();
4960
4047
  }
4961
- function createAdditionExpression() {
4962
- return new AdditionExpression();
4048
+ function createAdditionExpression$1() {
4049
+ return new AdditionExpression$1();
4963
4050
  }
4964
4051
  function createStringConcatenationExpression() {
4965
4052
  return new StringConcatenationExpression();
4966
4053
  }
4967
- function createMultiplicationExpression() {
4968
- return new MultiplicationExpression();
4054
+ function createMultiplicationExpression$1() {
4055
+ return new MultiplicationExpression$1();
4969
4056
  }
4970
4057
  const specialExpressions = {
4971
4058
  stringLiteral: createStringLiteralExpression(),
4972
4059
  numberLiteral: createNumberLiteralExpression(),
4973
4060
  booleanLiteral: createBooleanLiteralExpression(),
4974
- addition: createAdditionExpression(),
4061
+ addition: createAdditionExpression$1(),
4975
4062
  stringConcatenation: createStringConcatenationExpression(),
4976
- multiplication: createMultiplicationExpression(),
4063
+ multiplication: createMultiplicationExpression$1(),
4977
4064
  };
4978
4065
 
4979
- function createCoreExpressionEvaluator() {
4980
- return new ConfigurableExpressionEvaluator([
4981
- referencesExpressions,
4982
- logicalExpressions,
4983
- specialExpressions,
4984
- ]);
4066
+ function createCoreRegistry() {
4067
+ return createExpressionRegistry(referencesExpressions, logicalExpressions, specialExpressions);
4985
4068
  }
4986
4069
 
4987
4070
  function converterError(name, code, message, suggestions, type = 'runtime-error') {
@@ -5096,11 +4179,21 @@ const enhancedConverters = {
5096
4179
  }
5097
4180
  },
5098
4181
  JSON: (value, _context) => {
4182
+ if (!isString(value))
4183
+ return success(value, 'object');
4184
+ try {
4185
+ return success(JSON.parse(value), 'object');
4186
+ }
4187
+ catch (error) {
4188
+ return converterError('JSON', 'JSON_PARSE_FAILED', errorMsg('Failed to parse value as JSON', error), ['Check JSON syntax and escaping', 'Use `as JSONString` to stringify a value instead'], 'syntax-error');
4189
+ }
4190
+ },
4191
+ JSONString: (value, _context) => {
5099
4192
  try {
5100
4193
  return success(JSON.stringify(value), 'string');
5101
4194
  }
5102
4195
  catch (error) {
5103
- return converterError('JSON', 'JSON_STRINGIFY_FAILED', errorMsg('Failed to convert value to JSON', error), [
4196
+ return converterError('JSONString', 'JSON_STRINGIFY_FAILED', errorMsg('Failed to stringify value as JSON', error), [
5104
4197
  'Check for circular references',
5105
4198
  'Ensure all properties are serializable',
5106
4199
  'Remove functions and undefined values',
@@ -5154,6 +4247,35 @@ const enhancedConverters = {
5154
4247
  ]);
5155
4248
  }
5156
4249
  },
4250
+ FormEncoded: (value, context) => {
4251
+ try {
4252
+ let values = value;
4253
+ if (value instanceof HTMLElement) {
4254
+ const extracted = enhancedConverters.Values(value, context);
4255
+ if (!extracted.success)
4256
+ return extracted;
4257
+ values = extracted.value;
4258
+ }
4259
+ if (!isObject(values))
4260
+ return success('', 'string');
4261
+ const params = new URLSearchParams();
4262
+ for (const [k, v] of Object.entries(values)) {
4263
+ if (v === undefined || v === null)
4264
+ continue;
4265
+ if (Array.isArray(v)) {
4266
+ for (const item of v)
4267
+ params.append(k, String(item));
4268
+ }
4269
+ else {
4270
+ params.append(k, String(v));
4271
+ }
4272
+ }
4273
+ return success(params.toString(), 'string');
4274
+ }
4275
+ catch (error) {
4276
+ return converterError('FormEncoded', 'FORM_ENCODE_FAILED', errorMsg('Failed to URL-encode values', error), ['Ensure input is a form element or plain object of scalar/array values']);
4277
+ }
4278
+ },
5157
4279
  };
5158
4280
  const AsExpressionInputSchema = v.object({
5159
4281
  value: v.any(),
@@ -5186,10 +4308,15 @@ class AsExpression extends BaseExpressionImpl {
5186
4308
  expectedOutput: { name: 'John', age: '25' },
5187
4309
  },
5188
4310
  {
5189
- input: '[1,2,3] as JSON',
5190
- description: 'Convert array to JSON string',
4311
+ input: '[1,2,3] as JSONString',
4312
+ description: 'Convert array to JSON string (upstream 0.9.90: use JSONString, not JSON)',
5191
4313
  expectedOutput: '[1,2,3]',
5192
4314
  },
4315
+ {
4316
+ input: '\'{"a":1}\' as JSON',
4317
+ description: 'Parse a JSON string (upstream 0.9.90: as JSON now parses)',
4318
+ expectedOutput: { a: 1 },
4319
+ },
5193
4320
  {
5194
4321
  input: '"2023-12-25" as Date',
5195
4322
  description: 'Parse date string',
@@ -5254,8 +4381,8 @@ class AsExpression extends BaseExpressionImpl {
5254
4381
  },
5255
4382
  {
5256
4383
  title: 'Array to JSON serialization',
5257
- code: 'put items as JSON into storage',
5258
- explanation: 'Convert array to JSON string for storage',
4384
+ code: 'put items as JSONString into storage',
4385
+ explanation: 'Convert array to JSON string for storage (upstream 0.9.90: use `as JSONString`)',
5259
4386
  output: '"[1,2,3]"',
5260
4387
  },
5261
4388
  {
@@ -5326,6 +4453,8 @@ class AsExpression extends BaseExpressionImpl {
5326
4453
  obj: 'Object',
5327
4454
  date: 'Date',
5328
4455
  json: 'JSON',
4456
+ jsonstring: 'JSONString',
4457
+ formencoded: 'FormEncoded',
5329
4458
  };
5330
4459
  const aliasedType = typeAliases[lowerType];
5331
4460
  if (aliasedType) {
@@ -5672,14 +4801,24 @@ const defaultConversions = {
5672
4801
  const [year, month, day] = value.split('-').map(Number);
5673
4802
  return new Date(year, month - 1, day);
5674
4803
  }
5675
- const date = new Date(value);
5676
- return date;
4804
+ const date = new Date(value);
4805
+ return date;
4806
+ },
4807
+ JSON: (value) => {
4808
+ if (!isString(value))
4809
+ return value;
4810
+ try {
4811
+ return JSON.parse(value);
4812
+ }
4813
+ catch {
4814
+ return value;
4815
+ }
5677
4816
  },
5678
- JSON: (value) => {
4817
+ JSONString: (value) => {
5679
4818
  try {
5680
4819
  return JSON.stringify(value);
5681
4820
  }
5682
- catch (error) {
4821
+ catch {
5683
4822
  return '{}';
5684
4823
  }
5685
4824
  },
@@ -5739,9 +4878,27 @@ const defaultConversions = {
5739
4878
  }
5740
4879
  return {};
5741
4880
  },
4881
+ FormEncoded: (value, context) => {
4882
+ const values = value instanceof HTMLElement ? defaultConversions.Values(value, context) : value;
4883
+ if (!isObject(values))
4884
+ return '';
4885
+ const params = new URLSearchParams();
4886
+ for (const [k, v] of Object.entries(values)) {
4887
+ if (v === undefined || v === null)
4888
+ continue;
4889
+ if (Array.isArray(v)) {
4890
+ for (const item of v)
4891
+ params.append(k, String(item));
4892
+ }
4893
+ else {
4894
+ params.append(k, String(v));
4895
+ }
4896
+ }
4897
+ return params.toString();
4898
+ },
5742
4899
  'Values:Form': (value, context) => {
5743
4900
  const values = defaultConversions.Values(value, context);
5744
- return new URLSearchParams(values).toString();
4901
+ return defaultConversions.FormEncoded(values, context);
5745
4902
  },
5746
4903
  'Values:JSON': (value, context) => {
5747
4904
  const values = defaultConversions.Values(value, context);
@@ -5857,6 +5014,8 @@ const asExpression = {
5857
5014
  obj: 'Object',
5858
5015
  date: 'Date',
5859
5016
  json: 'JSON',
5017
+ jsonstring: 'JSONString',
5018
+ formencoded: 'FormEncoded',
5860
5019
  };
5861
5020
  const aliasedType = typeAliases[lowerType];
5862
5021
  if (aliasedType) {
@@ -6595,14 +5754,127 @@ const positionalExpressions = {
6595
5754
  previousWithin: previousWithinExpression,
6596
5755
  };
6597
5756
 
6598
- function createCommonExpressionEvaluator() {
6599
- return new ConfigurableExpressionEvaluator([
6600
- referencesExpressions,
6601
- logicalExpressions,
6602
- specialExpressions,
6603
- conversionExpressions,
6604
- positionalExpressions,
6605
- ]);
5757
+ function createCommonRegistry() {
5758
+ return createExpressionRegistry(referencesExpressions, logicalExpressions, specialExpressions, conversionExpressions, positionalExpressions);
5759
+ }
5760
+
5761
+ function isInputElement(el) {
5762
+ return (el !== null && typeof el === 'object' && 'tagName' in el && el.tagName === 'INPUT');
5763
+ }
5764
+ function isFormElement(el) {
5765
+ if (el === null || typeof el !== 'object' || !('tagName' in el)) {
5766
+ return false;
5767
+ }
5768
+ const tag = el.tagName;
5769
+ return tag === 'INPUT' || tag === 'SELECT' || tag === 'TEXTAREA';
5770
+ }
5771
+ function isHTMLElement$1(el) {
5772
+ return (el !== null &&
5773
+ typeof el === 'object' &&
5774
+ 'nodeType' in el &&
5775
+ el.nodeType === 1 &&
5776
+ 'style' in el);
5777
+ }
5778
+ function isOptionElement(el) {
5779
+ return (el !== null &&
5780
+ typeof el !== 'undefined' &&
5781
+ typeof el === 'object' &&
5782
+ 'tagName' in el &&
5783
+ el.tagName === 'OPTION');
5784
+ }
5785
+
5786
+ function isHTMLElement(value) {
5787
+ return value instanceof HTMLElement;
5788
+ }
5789
+ const BOOLEAN_ATTRIBUTES = new Set([
5790
+ 'disabled',
5791
+ 'readonly',
5792
+ 'required',
5793
+ 'checked',
5794
+ 'selected',
5795
+ 'hidden',
5796
+ 'open',
5797
+ 'autofocus',
5798
+ 'autoplay',
5799
+ 'controls',
5800
+ 'loop',
5801
+ 'muted',
5802
+ 'multiple',
5803
+ 'reversed',
5804
+ 'defer',
5805
+ 'async',
5806
+ 'novalidate',
5807
+ 'formnovalidate',
5808
+ 'ismap',
5809
+ ]);
5810
+ function accessAttribute(element, attrName) {
5811
+ if (BOOLEAN_ATTRIBUTES.has(attrName.toLowerCase())) {
5812
+ return element.hasAttribute(attrName);
5813
+ }
5814
+ return element.getAttribute(attrName);
5815
+ }
5816
+ function hasAttribute(element, attrName) {
5817
+ return element.hasAttribute(attrName);
5818
+ }
5819
+ const SPECIAL_DOM_PROPERTIES = {
5820
+ id: el => el.id,
5821
+ classname: el => el.className,
5822
+ class: el => el.className,
5823
+ tagname: el => el.tagName.toLowerCase(),
5824
+ innertext: el => el.textContent?.trim(),
5825
+ innerHTML: el => el.innerHTML,
5826
+ outerhtml: el => el.outerHTML,
5827
+ value: el => (isFormElement(el) ? el.value : undefined),
5828
+ checked: el => (isInputElement(el) ? el.checked : undefined),
5829
+ disabled: el => ('disabled' in el ? el.disabled : undefined),
5830
+ selected: el => (isOptionElement(el) ? el.selected : undefined),
5831
+ tabindex: el => (isHTMLElement$1(el) ? el.tabIndex : undefined),
5832
+ hidden: el => (isHTMLElement$1(el) ? el.hidden : undefined),
5833
+ style: el => getComputedStyle(el),
5834
+ children: el => Array.from(el.children),
5835
+ parent: el => el.parentElement,
5836
+ firstchild: el => el.firstElementChild,
5837
+ lastchild: el => el.lastElementChild,
5838
+ nextsibling: el => el.nextElementSibling,
5839
+ previoussibling: el => el.previousElementSibling,
5840
+ values: el => collectFormValues(el),
5841
+ };
5842
+ function collectFormValues(el) {
5843
+ if (el instanceof HTMLFormElement)
5844
+ return new FormData(el);
5845
+ const fd = new FormData();
5846
+ el.querySelectorAll('input, select, textarea').forEach((input) => {
5847
+ const name = input.getAttribute('name');
5848
+ if (name && 'value' in input)
5849
+ fd.append(name, input.value);
5850
+ });
5851
+ return fd;
5852
+ }
5853
+ function getElementProperty(element, property) {
5854
+ if (property.startsWith('computed-')) {
5855
+ const cssProperty = property.slice('computed-'.length);
5856
+ if (isHTMLElement(element)) {
5857
+ const computedStyle = getComputedStyle(element);
5858
+ return computedStyle.getPropertyValue(cssProperty);
5859
+ }
5860
+ return undefined;
5861
+ }
5862
+ if (property.startsWith('@')) {
5863
+ const attrName = property.slice(1);
5864
+ return accessAttribute(element, attrName);
5865
+ }
5866
+ const specialHandler = SPECIAL_DOM_PROPERTIES[property.toLowerCase()];
5867
+ if (specialHandler) {
5868
+ return specialHandler(element);
5869
+ }
5870
+ if (hasAttribute(element, property)) {
5871
+ return accessAttribute(element, property);
5872
+ }
5873
+ const value = element[property];
5874
+ if (isFunction(value)) {
5875
+ return value.bind(element);
5876
+ }
5877
+ return value;
6606
5878
  }
6607
5879
 
6608
5880
  const UNSAFE_PROPS = new Set(['__proto__', 'constructor', 'prototype']);
@@ -6844,16 +6116,271 @@ const propertiesExpressions = {
6844
6116
  idReference: idReferenceExpression,
6845
6117
  };
6846
6118
 
6847
- function createFullExpressionEvaluator() {
6848
- return new ConfigurableExpressionEvaluator([
6849
- referencesExpressions,
6850
- logicalExpressions,
6851
- specialExpressions,
6852
- conversionExpressions,
6853
- positionalExpressions,
6854
- propertiesExpressions,
6855
- ]);
6119
+ function createFullRegistry() {
6120
+ return createExpressionRegistry(referencesExpressions, logicalExpressions, specialExpressions, conversionExpressions, positionalExpressions, propertiesExpressions);
6121
+ }
6122
+
6123
+ class AdditionExpression {
6124
+ constructor() {
6125
+ this.name = 'addition';
6126
+ this.category = 'Special';
6127
+ this.syntax = 'left + right';
6128
+ this.outputType = 'number';
6129
+ this.metadata = { category: 'Special', complexity: 'simple' };
6130
+ }
6131
+ async evaluate(_context, input) {
6132
+ const validation = this.validate(input);
6133
+ if (!validation.isValid) {
6134
+ return { success: false, errors: validation.errors, suggestions: validation.suggestions };
6135
+ }
6136
+ try {
6137
+ const { left, right } = input;
6138
+ const leftNum = toNumber(left, 'left operand');
6139
+ const rightNum = toNumber(right, 'right operand');
6140
+ const result = ensureFinite(leftNum + rightNum, 'addition');
6141
+ return { success: true, value: result, type: 'number' };
6142
+ }
6143
+ catch (error) {
6144
+ return {
6145
+ success: false,
6146
+ errors: [
6147
+ createError('runtime-error', `Addition failed: ${error instanceof Error ? error.message : String(error)}`),
6148
+ ],
6149
+ suggestions: ['Ensure both operands are numeric'],
6150
+ };
6151
+ }
6152
+ }
6153
+ validate(input) {
6154
+ const result = validateBinaryInput(input);
6155
+ if (!result.isValid)
6156
+ return result;
6157
+ const { left, right } = input;
6158
+ if (!canBeNumeric(left)) {
6159
+ return {
6160
+ isValid: false,
6161
+ errors: [
6162
+ createError('type-mismatch', `Left operand cannot be converted to number: ${String(left)}`),
6163
+ ],
6164
+ suggestions: ['Provide a numeric value for left operand'],
6165
+ };
6166
+ }
6167
+ if (!canBeNumeric(right)) {
6168
+ return {
6169
+ isValid: false,
6170
+ errors: [
6171
+ createError('type-mismatch', `Right operand cannot be converted to number: ${String(right)}`),
6172
+ ],
6173
+ suggestions: ['Provide a numeric value for right operand'],
6174
+ };
6175
+ }
6176
+ return { isValid: true, errors: [], suggestions: [] };
6177
+ }
6178
+ }
6179
+ class SubtractionExpression {
6180
+ constructor() {
6181
+ this.name = 'subtraction';
6182
+ this.category = 'Special';
6183
+ this.syntax = 'left - right';
6184
+ this.outputType = 'number';
6185
+ this.metadata = { category: 'Special', complexity: 'simple' };
6186
+ }
6187
+ async evaluate(_context, input) {
6188
+ const validation = this.validate(input);
6189
+ if (!validation.isValid) {
6190
+ return { success: false, errors: validation.errors, suggestions: validation.suggestions };
6191
+ }
6192
+ try {
6193
+ const { left, right } = input;
6194
+ const leftNum = toNumber(left, 'left operand');
6195
+ const rightNum = toNumber(right, 'right operand');
6196
+ const result = ensureFinite(leftNum - rightNum, 'subtraction');
6197
+ return { success: true, value: result, type: 'number' };
6198
+ }
6199
+ catch (error) {
6200
+ return {
6201
+ success: false,
6202
+ errors: [
6203
+ createError('runtime-error', `Subtraction failed: ${error instanceof Error ? error.message : String(error)}`),
6204
+ ],
6205
+ suggestions: ['Ensure both operands are numeric'],
6206
+ };
6207
+ }
6208
+ }
6209
+ validate(input) {
6210
+ const addExpr = new AdditionExpression();
6211
+ return addExpr.validate(input);
6212
+ }
6213
+ }
6214
+ class MultiplicationExpression {
6215
+ constructor() {
6216
+ this.name = 'multiplication';
6217
+ this.category = 'Special';
6218
+ this.syntax = 'left * right';
6219
+ this.outputType = 'number';
6220
+ this.metadata = { category: 'Special', complexity: 'simple' };
6221
+ }
6222
+ async evaluate(_context, input) {
6223
+ const validation = this.validate(input);
6224
+ if (!validation.isValid) {
6225
+ return { success: false, errors: validation.errors, suggestions: validation.suggestions };
6226
+ }
6227
+ try {
6228
+ const { left, right } = input;
6229
+ const leftNum = toNumber(left, 'left operand');
6230
+ const rightNum = toNumber(right, 'right operand');
6231
+ const result = ensureFinite(leftNum * rightNum, 'multiplication');
6232
+ return { success: true, value: result, type: 'number' };
6233
+ }
6234
+ catch (error) {
6235
+ return {
6236
+ success: false,
6237
+ errors: [
6238
+ createError('runtime-error', `Multiplication failed: ${error instanceof Error ? error.message : String(error)}`),
6239
+ ],
6240
+ suggestions: ['Ensure both operands are numeric'],
6241
+ };
6242
+ }
6243
+ }
6244
+ validate(input) {
6245
+ const addExpr = new AdditionExpression();
6246
+ return addExpr.validate(input);
6247
+ }
6248
+ }
6249
+ class DivisionExpression {
6250
+ constructor() {
6251
+ this.name = 'division';
6252
+ this.category = 'Special';
6253
+ this.syntax = 'left / right';
6254
+ this.outputType = 'number';
6255
+ this.metadata = { category: 'Special', complexity: 'simple' };
6256
+ }
6257
+ async evaluate(_context, input) {
6258
+ const validation = this.validate(input);
6259
+ if (!validation.isValid) {
6260
+ return { success: false, errors: validation.errors, suggestions: validation.suggestions };
6261
+ }
6262
+ try {
6263
+ const { left, right } = input;
6264
+ const leftNum = toNumber(left, 'left operand');
6265
+ const rightNum = toNumber(right, 'right operand');
6266
+ const result = safeDivide(leftNum, rightNum, true);
6267
+ return { success: true, value: result, type: 'number' };
6268
+ }
6269
+ catch (error) {
6270
+ return {
6271
+ success: false,
6272
+ errors: [
6273
+ createError('runtime-error', `Division failed: ${error instanceof Error ? error.message : String(error)}`),
6274
+ ],
6275
+ suggestions: ['Ensure both operands are numeric'],
6276
+ };
6277
+ }
6278
+ }
6279
+ validate(input) {
6280
+ const addExpr = new AdditionExpression();
6281
+ return addExpr.validate(input);
6282
+ }
6283
+ }
6284
+ class ModuloExpression {
6285
+ constructor() {
6286
+ this.name = 'modulo';
6287
+ this.category = 'Special';
6288
+ this.syntax = 'left mod right';
6289
+ this.outputType = 'number';
6290
+ this.metadata = { category: 'Special', complexity: 'simple' };
6291
+ }
6292
+ async evaluate(_context, input) {
6293
+ const validation = this.validate(input);
6294
+ if (!validation.isValid) {
6295
+ return { success: false, errors: validation.errors, suggestions: validation.suggestions };
6296
+ }
6297
+ try {
6298
+ const { left, right } = input;
6299
+ const leftNum = toNumber(left, 'left operand');
6300
+ const rightNum = toNumber(right, 'right operand');
6301
+ const result = safeModulo(leftNum, rightNum);
6302
+ return { success: true, value: result, type: 'number' };
6303
+ }
6304
+ catch (error) {
6305
+ return {
6306
+ success: false,
6307
+ errors: [
6308
+ createError('runtime-error', `Modulo failed: ${error instanceof Error ? error.message : String(error)}`),
6309
+ ],
6310
+ suggestions: ['Ensure both operands are numeric and divisor is not zero'],
6311
+ };
6312
+ }
6313
+ }
6314
+ validate(input) {
6315
+ const addExpr = new AdditionExpression();
6316
+ return addExpr.validate(input);
6317
+ }
6318
+ }
6319
+ class PowerExpression {
6320
+ constructor() {
6321
+ this.name = 'power';
6322
+ this.category = 'Special';
6323
+ this.syntax = 'left ** right';
6324
+ this.outputType = 'number';
6325
+ this.metadata = { category: 'Special', complexity: 'simple' };
6326
+ }
6327
+ async evaluate(_context, input) {
6328
+ const validation = this.validate(input);
6329
+ if (!validation.isValid) {
6330
+ return { success: false, errors: validation.errors, suggestions: validation.suggestions };
6331
+ }
6332
+ try {
6333
+ const { left, right } = input;
6334
+ const leftNum = toNumber(left, 'left operand');
6335
+ const rightNum = toNumber(right, 'right operand');
6336
+ const result = ensureFinite(Math.pow(leftNum, rightNum), 'power');
6337
+ return { success: true, value: result, type: 'number' };
6338
+ }
6339
+ catch (error) {
6340
+ return {
6341
+ success: false,
6342
+ errors: [
6343
+ createError('runtime-error', `Power failed: ${error instanceof Error ? error.message : String(error)}`),
6344
+ ],
6345
+ suggestions: ['Ensure both operands are numeric'],
6346
+ };
6347
+ }
6348
+ }
6349
+ validate(input) {
6350
+ const addExpr = new AdditionExpression();
6351
+ return addExpr.validate(input);
6352
+ }
6353
+ }
6354
+ function createAdditionExpression() {
6355
+ return new AdditionExpression();
6356
+ }
6357
+ function createSubtractionExpression() {
6358
+ return new SubtractionExpression();
6359
+ }
6360
+ function createMultiplicationExpression() {
6361
+ return new MultiplicationExpression();
6362
+ }
6363
+ function createDivisionExpression() {
6364
+ return new DivisionExpression();
6365
+ }
6366
+ function createModuloExpression() {
6367
+ return new ModuloExpression();
6368
+ }
6369
+ function createPowerExpression() {
6370
+ return new PowerExpression();
6371
+ }
6372
+ const mathematicalExpressions = {
6373
+ addition: createAdditionExpression(),
6374
+ subtraction: createSubtractionExpression(),
6375
+ multiplication: createMultiplicationExpression(),
6376
+ division: createDivisionExpression(),
6377
+ modulo: createModuloExpression(),
6378
+ power: createPowerExpression(),
6379
+ };
6380
+
6381
+ function createFullExpressionRegistry() {
6382
+ return createExpressionRegistry(referencesExpressions, logicalExpressions, conversionExpressions, positionalExpressions, propertiesExpressions, specialExpressions, mathematicalExpressions);
6856
6383
  }
6857
6384
 
6858
- export { BaseExpressionEvaluator, ConfigurableExpressionEvaluator, conversionExpressions as conversion, conversionExpressions, createCommonExpressionEvaluator, createCoreExpressionEvaluator, createFullExpressionEvaluator, logicalExpressions as logical, logicalExpressions, positionalExpressions as positional, positionalExpressions, propertiesExpressions as properties, propertiesExpressions, referencesExpressions as references, referencesExpressions, specialExpressions as special, specialExpressions };
6385
+ export { conversionExpressions as conversion, conversionExpressions, createCommonRegistry, createCoreRegistry, createExpressionRegistry, createFullExpressionRegistry, createFullRegistry, logicalExpressions as logical, logicalExpressions, positionalExpressions as positional, positionalExpressions, propertiesExpressions as properties, propertiesExpressions, referencesExpressions as references, referencesExpressions, specialExpressions as special, specialExpressions };
6859
6386
  //# sourceMappingURL=index.mjs.map