@hyperfixi/core 3.3.0 → 4.0.1

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 (378) hide show
  1. package/README.md +57 -179
  2. package/dist/ast-utils/index.cjs +74 -806
  3. package/dist/ast-utils/index.d.ts +1 -1
  4. package/dist/ast-utils/index.mjs +74 -805
  5. package/dist/ast-utils/interchange/engine-positions.d.ts +3 -0
  6. package/dist/ast-utils/interchange/index.d.ts +1 -2
  7. package/dist/hyperfixi.js +19 -2
  8. package/dist/index.d.ts +2 -22
  9. package/dist/index.mjs +3 -29128
  10. package/dist/lsp-metadata.cjs +77 -73
  11. package/dist/lsp-metadata.d.ts +4 -4
  12. package/dist/lsp-metadata.mjs +77 -73
  13. package/dist/metadata.cjs +34 -266
  14. package/dist/metadata.d.ts +31 -26
  15. package/dist/metadata.mjs +34 -266
  16. package/dist/multilingual/index.cjs +16 -382
  17. package/dist/multilingual/index.d.ts +4 -32
  18. package/dist/multilingual/index.mjs +15 -377
  19. package/dist/reference/index.cjs +67 -216
  20. package/dist/reference/index.d.ts +0 -3
  21. package/dist/reference/index.mjs +68 -216
  22. package/dist/version.d.ts +1 -1
  23. package/package.json +13 -179
  24. package/dist/__test-utils__/context-builders.d.ts +0 -42
  25. package/dist/__test-utils__/error-testing.d.ts +0 -18
  26. package/dist/__test-utils__/index.d.ts +0 -6
  27. package/dist/__test-utils__/mock-types.d.ts +0 -57
  28. package/dist/__test-utils__/parser-context-mock.d.ts +0 -7
  29. package/dist/__test-utils__/parser-helpers.d.ts +0 -38
  30. package/dist/api/hyperscript-api.d.ts +0 -90
  31. package/dist/api/lokascript-api.d.ts +0 -9
  32. package/dist/ast/command-slots.d.ts +0 -140
  33. package/dist/ast/guards.d.ts +0 -15
  34. package/dist/ast/legacy.d.ts +0 -15
  35. package/dist/ast/nodes.d.ts +0 -243
  36. package/dist/ast-utils/interchange/from-core.d.ts +0 -12
  37. package/dist/ast-utils/interchange/to-core.d.ts +0 -8
  38. package/dist/behaviors/boosted.d.ts +0 -29
  39. package/dist/behaviors/history-swap.d.ts +0 -24
  40. package/dist/behaviors/index.cjs +0 -1155
  41. package/dist/behaviors/index.d.ts +0 -4
  42. package/dist/behaviors/index.mjs +0 -1145
  43. package/dist/bundle-generator/executor-core.d.ts +0 -4
  44. package/dist/bundle-generator/generator.d.ts +0 -4
  45. package/dist/bundle-generator/index.cjs +0 -2804
  46. package/dist/bundle-generator/index.d.ts +0 -6
  47. package/dist/bundle-generator/index.mjs +0 -2779
  48. package/dist/bundle-generator/parser-templates.d.ts +0 -6
  49. package/dist/bundle-generator/template-capabilities.d.ts +0 -12
  50. package/dist/bundle-generator/templates.d.ts +0 -12
  51. package/dist/bundle-generator/types.d.ts +0 -34
  52. package/dist/chunks/bridge-CI9SOl8u.js +0 -2
  53. package/dist/chunks/browser-modular-7CpI5VF2.js +0 -2
  54. package/dist/chunks/index-BwXDEK0m.js +0 -2
  55. package/dist/chunks/index-DQi2o8Lk.js +0 -2
  56. package/dist/chunks/index-uCOQ8Qn0.js +0 -2
  57. package/dist/commands/advanced/js.d.ts +0 -40
  58. package/dist/commands/animation/measure.d.ts +0 -43
  59. package/dist/commands/animation/settle.d.ts +0 -38
  60. package/dist/commands/animation/start-view-transition.d.ts +0 -38
  61. package/dist/commands/animation/take.d.ts +0 -41
  62. package/dist/commands/animation/transition.d.ts +0 -49
  63. package/dist/commands/async/fetch.d.ts +0 -61
  64. package/dist/commands/async/wait.d.ts +0 -51
  65. package/dist/commands/behaviors/install.d.ts +0 -40
  66. package/dist/commands/content/append.d.ts +0 -26
  67. package/dist/commands/content/insertion-base.d.ts +0 -60
  68. package/dist/commands/content/prepend.d.ts +0 -26
  69. package/dist/commands/control-flow/break.d.ts +0 -29
  70. package/dist/commands/control-flow/continue.d.ts +0 -29
  71. package/dist/commands/control-flow/exit.d.ts +0 -29
  72. package/dist/commands/control-flow/halt.d.ts +0 -39
  73. package/dist/commands/control-flow/if.d.ts +0 -58
  74. package/dist/commands/control-flow/repeat.d.ts +0 -50
  75. package/dist/commands/control-flow/return.d.ts +0 -33
  76. package/dist/commands/control-flow/signal-base.d.ts +0 -18
  77. package/dist/commands/control-flow/throw.d.ts +0 -34
  78. package/dist/commands/control-flow/unless.d.ts +0 -3
  79. package/dist/commands/data/clear.d.ts +0 -37
  80. package/dist/commands/data/decrement.d.ts +0 -3
  81. package/dist/commands/data/default.d.ts +0 -60
  82. package/dist/commands/data/get.d.ts +0 -35
  83. package/dist/commands/data/increment.d.ts +0 -42
  84. package/dist/commands/data/set.d.ts +0 -76
  85. package/dist/commands/decorators/index.d.ts +0 -14
  86. package/dist/commands/dom/add.d.ts +0 -44
  87. package/dist/commands/dom/close.d.ts +0 -32
  88. package/dist/commands/dom/dom-modification-base.d.ts +0 -48
  89. package/dist/commands/dom/empty.d.ts +0 -32
  90. package/dist/commands/dom/hide.d.ts +0 -28
  91. package/dist/commands/dom/make.d.ts +0 -34
  92. package/dist/commands/dom/open.d.ts +0 -34
  93. package/dist/commands/dom/process-partials.d.ts +0 -51
  94. package/dist/commands/dom/put.d.ts +0 -42
  95. package/dist/commands/dom/remove.d.ts +0 -46
  96. package/dist/commands/dom/reset.d.ts +0 -32
  97. package/dist/commands/dom/select.d.ts +0 -32
  98. package/dist/commands/dom/show.d.ts +0 -29
  99. package/dist/commands/dom/swap.d.ts +0 -65
  100. package/dist/commands/dom/toggle.d.ts +0 -69
  101. package/dist/commands/dom/visibility-base.d.ts +0 -22
  102. package/dist/commands/events/send.d.ts +0 -3
  103. package/dist/commands/events/trigger.d.ts +0 -49
  104. package/dist/commands/execution/blur.d.ts +0 -32
  105. package/dist/commands/execution/call.d.ts +0 -35
  106. package/dist/commands/execution/focus.d.ts +0 -32
  107. package/dist/commands/execution/pseudo-command.d.ts +0 -41
  108. package/dist/commands/helpers/attribute-manipulation.d.ts +0 -11
  109. package/dist/commands/helpers/attribute-target.d.ts +0 -9
  110. package/dist/commands/helpers/batch-dom-operations.d.ts +0 -12
  111. package/dist/commands/helpers/body-ops.d.ts +0 -10
  112. package/dist/commands/helpers/class-manipulation.d.ts +0 -11
  113. package/dist/commands/helpers/condition-helpers.d.ts +0 -4
  114. package/dist/commands/helpers/dom-mutation.d.ts +0 -16
  115. package/dist/commands/helpers/duration-parsing.d.ts +0 -8
  116. package/dist/commands/helpers/element-property-access.d.ts +0 -7
  117. package/dist/commands/helpers/element-resolution.d.ts +0 -16
  118. package/dist/commands/helpers/error-helpers.d.ts +0 -17
  119. package/dist/commands/helpers/event-helpers.d.ts +0 -13
  120. package/dist/commands/helpers/event-waiting.d.ts +0 -37
  121. package/dist/commands/helpers/index.d.ts +0 -32
  122. package/dist/commands/helpers/input-validator.d.ts +0 -23
  123. package/dist/commands/helpers/loop-executor.d.ts +0 -56
  124. package/dist/commands/helpers/numeric-target-parser.d.ts +0 -21
  125. package/dist/commands/helpers/property-target.d.ts +0 -20
  126. package/dist/commands/helpers/selector-type-detection.d.ts +0 -24
  127. package/dist/commands/helpers/slots.d.ts +0 -5
  128. package/dist/commands/helpers/smart-element.d.ts +0 -16
  129. package/dist/commands/helpers/style-manipulation.d.ts +0 -16
  130. package/dist/commands/helpers/target-elements.d.ts +0 -5
  131. package/dist/commands/helpers/temporal-modifiers.d.ts +0 -15
  132. package/dist/commands/helpers/url-argument-parser.d.ts +0 -13
  133. package/dist/commands/helpers/url-validation.d.ts +0 -7
  134. package/dist/commands/helpers/variable-access.d.ts +0 -13
  135. package/dist/commands/helpers/visibility-target-parser.d.ts +0 -15
  136. package/dist/commands/helpers/write-target.d.ts +0 -42
  137. package/dist/commands/index.cjs +0 -24168
  138. package/dist/commands/index.d.ts +0 -171
  139. package/dist/commands/index.mjs +0 -23981
  140. package/dist/commands/manifest.d.ts +0 -17
  141. package/dist/commands/navigation/go.d.ts +0 -58
  142. package/dist/commands/navigation/push-url.d.ts +0 -48
  143. package/dist/commands/navigation/replace-url.d.ts +0 -3
  144. package/dist/commands/navigation/scroll-to.d.ts +0 -43
  145. package/dist/commands/templates/render.d.ts +0 -47
  146. package/dist/commands/utility/beep.d.ts +0 -41
  147. package/dist/commands/utility/breakpoint.d.ts +0 -32
  148. package/dist/commands/utility/copy.d.ts +0 -41
  149. package/dist/commands/utility/log.d.ts +0 -36
  150. package/dist/commands/utility/pick.d.ts +0 -47
  151. package/dist/commands/utility/tell.d.ts +0 -39
  152. package/dist/compatibility/browser-bundle-classic.d.ts +0 -17
  153. package/dist/compatibility/browser-bundle-hybrid-complete.d.ts +0 -22
  154. package/dist/compatibility/browser-bundle-hybrid-hx.d.ts +0 -43
  155. package/dist/compatibility/browser-bundle-lite.d.ts +0 -15
  156. package/dist/compatibility/browser-bundle-modular.d.ts +0 -18
  157. package/dist/compatibility/browser-bundle-multilingual.d.ts +0 -19
  158. package/dist/compatibility/browser-bundle-semantic-complete.d.ts +0 -24
  159. package/dist/compatibility/browser-bundle-textshelf-minimal.d.ts +0 -16
  160. package/dist/compatibility/browser-bundle-textshelf-profile.d.ts +0 -18
  161. package/dist/compatibility/browser-modular.d.ts +0 -42
  162. package/dist/compatibility/browser-tests/helpers/semantic-page.d.ts +0 -3
  163. package/dist/compatibility/browser-tests/test-utils.d.ts +0 -21
  164. package/dist/compatibility/bundle-shell.d.ts +0 -13
  165. package/dist/compatibility/bundle-sources.d.ts +0 -4
  166. package/dist/compatibility/eval-hyperscript.d.ts +0 -16
  167. package/dist/compatibility/hyperscript-adapter.d.ts +0 -38
  168. package/dist/core/ast-property-utils.d.ts +0 -2
  169. package/dist/core/context.d.ts +0 -19
  170. package/dist/core/dom.d.ts +0 -15
  171. package/dist/core/evaluator-types.d.ts +0 -5
  172. package/dist/core/events.d.ts +0 -48
  173. package/dist/core/executor.d.ts +0 -34
  174. package/dist/core/expression-evaluator.d.ts +0 -6
  175. package/dist/core/expression-registry.d.ts +0 -8
  176. package/dist/core/scope-hooks.d.ts +0 -24
  177. package/dist/debug/debug-controller.d.ts +0 -62
  178. package/dist/debug/index.d.ts +0 -5
  179. package/dist/dom/attribute-processor.d.ts +0 -75
  180. package/dist/dom/detect-language.d.ts +0 -3
  181. package/dist/dom/minimal-attribute-processor.d.ts +0 -20
  182. package/dist/expressions/base-expression.d.ts +0 -27
  183. package/dist/expressions/bundles/common-expressions.d.ts +0 -10
  184. package/dist/expressions/bundles/core-expressions.d.ts +0 -8
  185. package/dist/expressions/bundles/full-expressions.d.ts +0 -11
  186. package/dist/expressions/bundles/index.d.ts +0 -7
  187. package/dist/expressions/collection/index.d.ts +0 -10
  188. package/dist/expressions/conversion/index.d.ts +0 -31
  189. package/dist/expressions/expression-tiers.d.ts +0 -13
  190. package/dist/expressions/index.cjs +0 -4331
  191. package/dist/expressions/index.d.ts +0 -13
  192. package/dist/expressions/index.mjs +0 -4312
  193. package/dist/expressions/logical/index.d.ts +0 -61
  194. package/dist/expressions/mathematical/index.d.ts +0 -80
  195. package/dist/expressions/positional/index.d.ts +0 -31
  196. package/dist/expressions/properties/index.d.ts +0 -27
  197. package/dist/expressions/property-access-utils.d.ts +0 -23
  198. package/dist/expressions/references/index.d.ts +0 -39
  199. package/dist/expressions/shared/comparison-utils.d.ts +0 -10
  200. package/dist/expressions/shared/index.d.ts +0 -10
  201. package/dist/expressions/shared/number-utils.d.ts +0 -8
  202. package/dist/expressions/shared/tracking.d.ts +0 -20
  203. package/dist/expressions/shared/validation-utils.d.ts +0 -13
  204. package/dist/expressions/special/index.d.ts +0 -78
  205. package/dist/expressions/type-helpers.d.ts +0 -11
  206. package/dist/expressions/type-registry.d.ts +0 -57
  207. package/dist/expressions/validation-helpers.d.ts +0 -15
  208. package/dist/htmx/hcon.d.ts +0 -9
  209. package/dist/htmx/htmx-attribute-processor.d.ts +0 -120
  210. package/dist/htmx/htmx-translator.d.ts +0 -22
  211. package/dist/htmx/i18n-hooks.d.ts +0 -18
  212. package/dist/htmx/i18n-orchestrator.d.ts +0 -16
  213. package/dist/htmx/index.d.ts +0 -3
  214. package/dist/htmx/lang-resolver.d.ts +0 -3
  215. package/dist/htmx/sse.d.ts +0 -60
  216. package/dist/htmx/ws.d.ts +0 -59
  217. package/dist/hyperfixi-browser-classic-i18n.js +0 -2
  218. package/dist/hyperfixi-browser.js +0 -2
  219. package/dist/hyperfixi-classic-i18n.js +0 -2
  220. package/dist/hyperfixi-hx-v4.js +0 -1
  221. package/dist/hyperfixi-hx.js +0 -1
  222. package/dist/hyperfixi-hybrid-complete.js +0 -1
  223. package/dist/hyperfixi-hybrid-hx.js +0 -1
  224. package/dist/hyperfixi-multilingual.js +0 -2
  225. package/dist/hyperfixi.mjs +0 -2
  226. package/dist/i18n/error-catalog.d.ts +0 -12
  227. package/dist/index.cjs +0 -29159
  228. package/dist/index.min.js +0 -2
  229. package/dist/lib/dom-globals-shim.d.ts +0 -2
  230. package/dist/lib/index.d.ts +0 -4
  231. package/dist/lib/morph-adapter.d.ts +0 -9
  232. package/dist/lib/swap-executor.d.ts +0 -12
  233. package/dist/lib/view-transitions.d.ts +0 -7
  234. package/dist/lokascript-browser-classic-i18n.js +0 -2
  235. package/dist/lokascript-browser.js +0 -2
  236. package/dist/lokascript-hybrid-complete.js +0 -1
  237. package/dist/lokascript-hybrid-hx.js +0 -1
  238. package/dist/lokascript-multilingual.js +0 -2
  239. package/dist/lse/index.cjs +0 -84
  240. package/dist/lse/index.d.ts +0 -15
  241. package/dist/lse/index.mjs +0 -71
  242. package/dist/multilingual/bridge.d.ts +0 -38
  243. package/dist/multilingual/schema-roles.d.ts +0 -3
  244. package/dist/parser/__types__/test-helpers.d.ts +0 -25
  245. package/dist/parser/command-grammar.d.ts +0 -14
  246. package/dist/parser/command-node-builder.d.ts +0 -46
  247. package/dist/parser/command-parsers/animation-commands.d.ts +0 -6
  248. package/dist/parser/command-parsers/async-commands.d.ts +0 -5
  249. package/dist/parser/command-parsers/control-flow-commands.d.ts +0 -7
  250. package/dist/parser/command-parsers/declared-commands.d.ts +0 -6
  251. package/dist/parser/command-parsers/dom-commands.d.ts +0 -11
  252. package/dist/parser/command-parsers/event-commands.d.ts +0 -4
  253. package/dist/parser/command-parsers/navigation-commands.d.ts +0 -6
  254. package/dist/parser/command-parsers/utility-commands.d.ts +0 -14
  255. package/dist/parser/command-parsers/variable-commands.d.ts +0 -12
  256. package/dist/parser/error-handler.d.ts +0 -34
  257. package/dist/parser/extensions.d.ts +0 -43
  258. package/dist/parser/full-parser.cjs +0 -7943
  259. package/dist/parser/full-parser.d.ts +0 -4
  260. package/dist/parser/full-parser.mjs +0 -7940
  261. package/dist/parser/helpers/ast-helpers.d.ts +0 -24
  262. package/dist/parser/helpers/parsing-helpers.d.ts +0 -19
  263. package/dist/parser/helpers/token-helpers.d.ts +0 -28
  264. package/dist/parser/hybrid/aliases.cjs +0 -44
  265. package/dist/parser/hybrid/aliases.d.ts +0 -7
  266. package/dist/parser/hybrid/aliases.mjs +0 -37
  267. package/dist/parser/hybrid/ast-types.cjs +0 -3
  268. package/dist/parser/hybrid/ast-types.d.ts +0 -97
  269. package/dist/parser/hybrid/ast-types.mjs +0 -2
  270. package/dist/parser/hybrid/index.cjs +0 -1185
  271. package/dist/parser/hybrid/index.d.ts +0 -6
  272. package/dist/parser/hybrid/index.mjs +0 -1175
  273. package/dist/parser/hybrid/parser-core.cjs +0 -1171
  274. package/dist/parser/hybrid/parser-core.d.ts +0 -69
  275. package/dist/parser/hybrid/parser-core.mjs +0 -1169
  276. package/dist/parser/hybrid/tokenizer.cjs +0 -255
  277. package/dist/parser/hybrid/tokenizer.d.ts +0 -9
  278. package/dist/parser/hybrid/tokenizer.mjs +0 -252
  279. package/dist/parser/hybrid-parser.cjs +0 -1249
  280. package/dist/parser/hybrid-parser.d.ts +0 -10
  281. package/dist/parser/hybrid-parser.mjs +0 -1242
  282. package/dist/parser/parser-constants.d.ts +0 -100
  283. package/dist/parser/parser-interface.d.ts +0 -12
  284. package/dist/parser/parser-types.d.ts +0 -164
  285. package/dist/parser/parser.d.ts +0 -165
  286. package/dist/parser/pratt-parser.d.ts +0 -41
  287. package/dist/parser/regex-parser.cjs +0 -422
  288. package/dist/parser/regex-parser.d.ts +0 -4
  289. package/dist/parser/regex-parser.mjs +0 -419
  290. package/dist/parser/runtime.d.ts +0 -14
  291. package/dist/parser/semantic-integration.d.ts +0 -17
  292. package/dist/parser/token-consumer.d.ts +0 -34
  293. package/dist/parser/token-predicates.d.ts +0 -77
  294. package/dist/parser/tokenizer.d.ts +0 -28
  295. package/dist/parser/types.d.ts +0 -105
  296. package/dist/performance/expression-cache.d.ts +0 -78
  297. package/dist/performance/integration.d.ts +0 -40
  298. package/dist/performance/production-monitor.d.ts +0 -67
  299. package/dist/registry/browser-types.cjs +0 -81
  300. package/dist/registry/browser-types.d.ts +0 -20
  301. package/dist/registry/browser-types.mjs +0 -76
  302. package/dist/registry/environment.cjs +0 -36
  303. package/dist/registry/environment.d.ts +0 -19
  304. package/dist/registry/environment.mjs +0 -30
  305. package/dist/registry/event-source-registry.d.ts +0 -54
  306. package/dist/registry/examples/server-commands.d.ts +0 -6
  307. package/dist/registry/examples/server-event-source.d.ts +0 -32
  308. package/dist/registry/index.cjs +0 -14055
  309. package/dist/registry/index.d.ts +0 -39
  310. package/dist/registry/index.mjs +0 -14039
  311. package/dist/registry/runtime-integration.d.ts +0 -23
  312. package/dist/registry/universal-types.cjs +0 -91
  313. package/dist/registry/universal-types.d.ts +0 -35
  314. package/dist/registry/universal-types.mjs +0 -86
  315. package/dist/runtime/cleanup-registry.d.ts +0 -47
  316. package/dist/runtime/command-adapter.d.ts +0 -69
  317. package/dist/runtime/environment.d.ts +0 -75
  318. package/dist/runtime/plugin.d.ts +0 -14
  319. package/dist/runtime/runtime-base.d.ts +0 -100
  320. package/dist/runtime/runtime-factory.d.ts +0 -29
  321. package/dist/runtime/runtime.d.ts +0 -20
  322. package/dist/runtime/temporal-modifiers.d.ts +0 -37
  323. package/dist/test-setup.d.ts +0 -28
  324. package/dist/test-utilities.d.ts +0 -39
  325. package/dist/types/base-types.d.ts +0 -231
  326. package/dist/types/code-fix.d.ts +0 -39
  327. package/dist/types/command-metadata.d.ts +0 -57
  328. package/dist/types/command-types.d.ts +0 -262
  329. package/dist/types/context-types.d.ts +0 -106
  330. package/dist/types/core-context.d.ts +0 -22
  331. package/dist/types/core.d.ts +0 -143
  332. package/dist/types/error-codes.d.ts +0 -207
  333. package/dist/types/expression-types.d.ts +0 -155
  334. package/dist/types/hooks.d.ts +0 -45
  335. package/dist/types/index.d.ts +0 -32
  336. package/dist/types/program.d.ts +0 -8
  337. package/dist/types/result.d.ts +0 -73
  338. package/dist/types/template-types.d.ts +0 -162
  339. package/dist/types/type-guards.d.ts +0 -24
  340. package/dist/types/unified-types.d.ts +0 -91
  341. package/dist/utils/beep.d.ts +0 -8
  342. package/dist/utils/debug-events.d.ts +0 -41
  343. package/dist/utils/debug.d.ts +0 -35
  344. package/dist/utils/dom-utils.d.ts +0 -16
  345. package/dist/utils/element-check.d.ts +0 -8
  346. package/dist/utils/keyboard-shortcuts.d.ts +0 -18
  347. package/dist/utils/performance.d.ts +0 -40
  348. package/dist/validation/command-pattern-validator.d.ts +0 -53
  349. package/dist/validation/common-validators.d.ts +0 -24
  350. package/dist/validation/lightweight-validators.d.ts +0 -113
  351. package/dist/validation/partial-validation-types.d.ts +0 -50
  352. package/dist/validation/partial-validator.d.ts +0 -6
  353. package/dist/validation/partial-warning-formatter.d.ts +0 -6
  354. package/dist/validation/validate-cli.d.ts +0 -41
  355. package/vocab/htmx/ar.js +0 -62
  356. package/vocab/htmx/bn.js +0 -65
  357. package/vocab/htmx/de.js +0 -83
  358. package/vocab/htmx/en.js +0 -24
  359. package/vocab/htmx/es.js +0 -79
  360. package/vocab/htmx/fr.js +0 -79
  361. package/vocab/htmx/he.js +0 -61
  362. package/vocab/htmx/hi.js +0 -81
  363. package/vocab/htmx/id.js +0 -76
  364. package/vocab/htmx/it.js +0 -79
  365. package/vocab/htmx/ja.js +0 -85
  366. package/vocab/htmx/ko.js +0 -81
  367. package/vocab/htmx/ms.js +0 -58
  368. package/vocab/htmx/pl.js +0 -80
  369. package/vocab/htmx/pt.js +0 -81
  370. package/vocab/htmx/qu.js +0 -83
  371. package/vocab/htmx/ru.js +0 -82
  372. package/vocab/htmx/sw.js +0 -79
  373. package/vocab/htmx/th.js +0 -67
  374. package/vocab/htmx/tl.js +0 -56
  375. package/vocab/htmx/tr.js +0 -86
  376. package/vocab/htmx/uk.js +0 -82
  377. package/vocab/htmx/vi.js +0 -59
  378. package/vocab/htmx/zh.js +0 -79
@@ -1,4331 +0,0 @@
1
- 'use strict';
2
-
3
- function createExpressionRegistry(...categories) {
4
- const map = new Map();
5
- for (const category of categories) {
6
- for (const [name, impl] of Object.entries(category)) {
7
- map.set(name, impl);
8
- }
9
- }
10
- return map;
11
- }
12
-
13
- class ExpressionTypeRegistry {
14
- constructor(config = {}) {
15
- this.types = new Map();
16
- this.coercionCache = new Map();
17
- this.config = {
18
- strictMode: false,
19
- cacheCoercions: true,
20
- ...config,
21
- };
22
- this.registerBuiltinTypes();
23
- }
24
- register(definition) {
25
- if (this.types.has(definition.name)) {
26
- console.warn(`ExpressionTypeRegistry: Overwriting existing type '${definition.name}'`);
27
- }
28
- this.types.set(definition.name, definition);
29
- }
30
- get(name) {
31
- return this.types.get(name);
32
- }
33
- has(name) {
34
- return this.types.has(name);
35
- }
36
- getTypeNames() {
37
- return Array.from(this.types.keys());
38
- }
39
- inferType(value) {
40
- for (const [name, def] of this.types) {
41
- if (def.isType(value)) {
42
- return name;
43
- }
44
- }
45
- return 'Unknown';
46
- }
47
- getHyperScriptType(value) {
48
- const typeName = this.inferType(value);
49
- const typeDef = this.types.get(typeName);
50
- return typeDef?.hyperscriptType ?? 'unknown';
51
- }
52
- coerce(value, targetType, context) {
53
- const targetDef = this.types.get(targetType);
54
- if (!targetDef) {
55
- if (this.config.strictMode) {
56
- throw new Error(`Unknown target type: ${targetType}`);
57
- }
58
- return null;
59
- }
60
- if (targetDef.isType(value)) {
61
- return value;
62
- }
63
- if (this.config.cacheCoercions) {
64
- const cacheKey = `${this.inferType(value)}:${targetType}:${JSON.stringify(value)}`;
65
- if (this.coercionCache.has(cacheKey)) {
66
- return this.coercionCache.get(cacheKey);
67
- }
68
- }
69
- const sourceType = this.inferType(value);
70
- const coerceFn = targetDef.coerceFrom?.[sourceType];
71
- if (coerceFn) {
72
- const result = coerceFn(value, context);
73
- if (this.config.cacheCoercions && result !== null) {
74
- const cacheKey = `${sourceType}:${targetType}:${JSON.stringify(value)}`;
75
- this.coercionCache.set(cacheKey, result);
76
- }
77
- return result;
78
- }
79
- return targetDef.defaultValue;
80
- }
81
- canCoerce(value, targetType) {
82
- const targetDef = this.types.get(targetType);
83
- if (!targetDef)
84
- return false;
85
- if (targetDef.isType(value))
86
- return true;
87
- const sourceType = this.inferType(value);
88
- return targetDef.coerceFrom?.[sourceType] !== undefined;
89
- }
90
- getCoercionInfo(sourceType, targetType) {
91
- const targetDef = this.types.get(targetType);
92
- if (!targetDef)
93
- return { possible: false, direct: false };
94
- if (sourceType === targetType) {
95
- return { possible: true, direct: true };
96
- }
97
- if (targetDef.coerceFrom?.[sourceType]) {
98
- return { possible: true, direct: true };
99
- }
100
- return { possible: false, direct: false };
101
- }
102
- clearCache() {
103
- this.coercionCache.clear();
104
- }
105
- getStats() {
106
- return {
107
- typeCount: this.types.size,
108
- cacheSize: this.coercionCache.size,
109
- typeNames: this.getTypeNames(),
110
- };
111
- }
112
- registerBuiltinTypes() {
113
- this.register({
114
- name: 'String',
115
- hyperscriptType: 'string',
116
- tsType: 'string',
117
- isType: (v) => typeof v === 'string',
118
- defaultValue: '',
119
- description: 'Text string value',
120
- examples: ['hello', 'world', ''],
121
- coerceFrom: {
122
- Number: v => String(v),
123
- Boolean: v => String(v),
124
- Null: () => '',
125
- Undefined: () => '',
126
- Array: v => (Array.isArray(v) ? v.join(', ') : null),
127
- Object: v => {
128
- try {
129
- return JSON.stringify(v);
130
- }
131
- catch {
132
- return String(v);
133
- }
134
- },
135
- Element: v => (v instanceof Element ? (v.textContent ?? v.outerHTML) : null),
136
- },
137
- });
138
- this.register({
139
- name: 'Number',
140
- hyperscriptType: 'number',
141
- tsType: 'number',
142
- isType: (v) => typeof v === 'number' && !isNaN(v),
143
- defaultValue: 0,
144
- description: 'Numeric value (integer or float)',
145
- examples: [0, 1, 3.14, -42],
146
- coerceFrom: {
147
- String: v => {
148
- const n = parseFloat(v);
149
- return isNaN(n) ? null : n;
150
- },
151
- Boolean: v => (v ? 1 : 0),
152
- Null: () => 0,
153
- Undefined: () => null,
154
- },
155
- });
156
- this.register({
157
- name: 'Boolean',
158
- hyperscriptType: 'boolean',
159
- tsType: 'boolean',
160
- isType: (v) => typeof v === 'boolean',
161
- defaultValue: false,
162
- description: 'True or false value',
163
- examples: [true, false],
164
- coerceFrom: {
165
- String: v => {
166
- const s = v.toLowerCase().trim();
167
- if (s === 'true' || s === 'yes' || s === '1')
168
- return true;
169
- if (s === 'false' || s === 'no' || s === '0' || s === '')
170
- return false;
171
- return s.length > 0;
172
- },
173
- Number: v => v !== 0,
174
- Null: () => false,
175
- Undefined: () => false,
176
- Array: v => (Array.isArray(v) ? v.length > 0 : false),
177
- Element: v => v instanceof Element,
178
- ElementList: v => Array.isArray(v) && v.length > 0,
179
- },
180
- });
181
- this.register({
182
- name: 'Element',
183
- hyperscriptType: 'element',
184
- tsType: 'Element | HTMLElement',
185
- isType: (v) => v instanceof Element,
186
- defaultValue: null,
187
- description: 'DOM Element',
188
- coerceFrom: {
189
- String: (v, ctx) => {
190
- const selector = v;
191
- if (selector.startsWith('#') || selector.startsWith('.') || selector.match(/^[\w-]+$/)) {
192
- try {
193
- return document.querySelector(selector);
194
- }
195
- catch {
196
- return null;
197
- }
198
- }
199
- return null;
200
- },
201
- ElementList: v => (Array.isArray(v) && v.length > 0 ? v[0] : null),
202
- NodeList: v => {
203
- const list = v;
204
- return list.length > 0 ? list[0] : null;
205
- },
206
- },
207
- });
208
- this.register({
209
- name: 'ElementList',
210
- hyperscriptType: 'element-list',
211
- tsType: 'Element[]',
212
- isType: (v) => Array.isArray(v) && v.length > 0 && v.every(item => item instanceof Element),
213
- defaultValue: [],
214
- description: 'Array of DOM Elements',
215
- coerceFrom: {
216
- Element: v => (v instanceof Element ? [v] : []),
217
- NodeList: v => Array.from(v),
218
- String: v => {
219
- try {
220
- return Array.from(document.querySelectorAll(v));
221
- }
222
- catch {
223
- return [];
224
- }
225
- },
226
- Array: v => {
227
- const arr = v;
228
- if (arr.every(item => item instanceof Element)) {
229
- return arr;
230
- }
231
- return [];
232
- },
233
- },
234
- });
235
- this.register({
236
- name: 'Array',
237
- hyperscriptType: 'array',
238
- tsType: 'unknown[]',
239
- isType: (v) => Array.isArray(v),
240
- defaultValue: [],
241
- description: 'Array of values',
242
- coerceFrom: {
243
- String: v => {
244
- const s = v;
245
- try {
246
- const parsed = JSON.parse(s);
247
- if (Array.isArray(parsed))
248
- return parsed;
249
- }
250
- catch {
251
- }
252
- return s.split(',').map(item => item.trim());
253
- },
254
- ElementList: v => v,
255
- NodeList: v => Array.from(v),
256
- Object: v => Object.values(v),
257
- },
258
- });
259
- this.register({
260
- name: 'Object',
261
- hyperscriptType: 'object',
262
- tsType: 'Record<string, unknown>',
263
- isType: (v) => typeof v === 'object' && v !== null && !Array.isArray(v) && !(v instanceof Element),
264
- defaultValue: {},
265
- description: 'Plain JavaScript object',
266
- coerceFrom: {
267
- String: v => {
268
- try {
269
- const parsed = JSON.parse(v);
270
- if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
271
- return parsed;
272
- }
273
- }
274
- catch {
275
- }
276
- return null;
277
- },
278
- Array: v => {
279
- const arr = v;
280
- const obj = {};
281
- arr.forEach((item, index) => {
282
- obj[String(index)] = item;
283
- });
284
- return obj;
285
- },
286
- },
287
- });
288
- this.register({
289
- name: 'Null',
290
- hyperscriptType: 'null',
291
- tsType: 'null',
292
- isType: (v) => v === null,
293
- defaultValue: null,
294
- description: 'Null value',
295
- });
296
- this.register({
297
- name: 'Undefined',
298
- hyperscriptType: 'undefined',
299
- tsType: 'undefined',
300
- isType: (v) => v === undefined,
301
- defaultValue: undefined,
302
- description: 'Undefined value',
303
- });
304
- this.register({
305
- name: 'Function',
306
- hyperscriptType: 'function',
307
- tsType: 'Function',
308
- isType: (v) => typeof v === 'function',
309
- defaultValue: null,
310
- description: 'JavaScript function',
311
- });
312
- this.register({
313
- name: 'Event',
314
- hyperscriptType: 'event',
315
- tsType: 'Event',
316
- isType: (v) => v instanceof Event,
317
- defaultValue: null,
318
- description: 'DOM Event',
319
- });
320
- this.register({
321
- name: 'NodeList',
322
- hyperscriptType: 'element-list',
323
- tsType: 'NodeList',
324
- isType: (v) => v instanceof NodeList,
325
- defaultValue: null,
326
- description: 'DOM NodeList (typically from querySelectorAll)',
327
- coerceFrom: {
328
- Array: v => {
329
- return null;
330
- },
331
- },
332
- });
333
- this.register({
334
- name: 'Unknown',
335
- hyperscriptType: 'unknown',
336
- tsType: 'unknown',
337
- isType: (_v) => true,
338
- defaultValue: null,
339
- description: 'Unknown/any value type',
340
- });
341
- }
342
- }
343
- const expressionTypeRegistry = new ExpressionTypeRegistry();
344
-
345
- function isString(value) {
346
- const stringType = expressionTypeRegistry.get('String');
347
- return stringType ? stringType.isType(value) : typeof value === 'string';
348
- }
349
- function isNumber(value) {
350
- const numberType = expressionTypeRegistry.get('Number');
351
- return numberType ? numberType.isType(value) : typeof value === 'number';
352
- }
353
- function isBoolean(value) {
354
- const boolType = expressionTypeRegistry.get('Boolean');
355
- return boolType ? boolType.isType(value) : typeof value === 'boolean';
356
- }
357
- function isObject(value) {
358
- const objectType = expressionTypeRegistry.get('Object');
359
- return objectType ? objectType.isType(value) : typeof value === 'object' && value !== null;
360
- }
361
- function isFunction(value) {
362
- const funcType = expressionTypeRegistry.get('Function');
363
- return funcType ? funcType.isType(value) : typeof value === 'function';
364
- }
365
-
366
- const NUMBER_WORDS = {
367
- 1: 'one',
368
- 2: 'two',
369
- 3: 'three',
370
- 4: 'four',
371
- 5: 'five',
372
- };
373
- function numberToWord(n) {
374
- return NUMBER_WORDS[n] ?? String(n);
375
- }
376
- function validateArgCount(args, expected, expressionName, argNames) {
377
- if (args.length !== expected) {
378
- const argDesc = argNames ? ` (${argNames})` : '';
379
- return `${expressionName} requires exactly ${numberToWord(expected)} argument${expected === 1 ? '' : 's'}${argDesc}`;
380
- }
381
- return null;
382
- }
383
- function validateArgIsString(args, index, expressionName, argName) {
384
- if (typeof args[index] !== 'string') {
385
- const name = argName || `argument ${index + 1}`;
386
- return `${expressionName} ${name} must be a string`;
387
- }
388
- return null;
389
- }
390
- function validateArgIsNumber(args, index, expressionName, argName) {
391
- if (typeof args[index] !== 'number') {
392
- const name = argName;
393
- return `${expressionName} ${name} must be a number`;
394
- }
395
- return null;
396
- }
397
- function validateSingleStringArg(args, expressionName, argName) {
398
- return (validateArgCount(args, 1, expressionName, argName) ??
399
- validateArgIsString(args, 0, expressionName, argName));
400
- }
401
- function validateTwoArgs(args, expressionName) {
402
- return validateArgCount(args, 2, expressionName, 'left, right');
403
- }
404
- function validateNoArgs() {
405
- return null;
406
- }
407
- function validateMaxArgs(args, maximum, expressionName, argNames) {
408
- if (args.length > maximum) {
409
- const argDesc = argNames ? ` (${argNames})` : '';
410
- const maxStr = maximum === 1 ? 'one' : String(maximum);
411
- return `${expressionName} expression takes at most ${maxStr} argument${maximum === 1 ? '' : 's'}${argDesc}`;
412
- }
413
- return null;
414
- }
415
- function validateArgRange(args, min, max, expressionName, argNames) {
416
- if (args.length < min || args.length > max) {
417
- const argDesc = argNames ? ` (${argNames})` : '';
418
- return `${expressionName} requires ${min}-${max} arguments${argDesc}`;
419
- }
420
- return null;
421
- }
422
-
423
- const meExpression = {
424
- name: 'me',
425
- category: 'Reference',
426
- evaluatesTo: 'Element',
427
- async evaluate(context) {
428
- return context.me ?? null;
429
- },
430
- validate: validateNoArgs,
431
- };
432
- const youExpression = {
433
- name: 'you',
434
- category: 'Reference',
435
- evaluatesTo: 'Element',
436
- async evaluate(context) {
437
- return context.you ?? null;
438
- },
439
- validate: validateNoArgs,
440
- };
441
- const itExpression = {
442
- name: 'it',
443
- category: 'Reference',
444
- evaluatesTo: 'Any',
445
- async evaluate(context) {
446
- return context.it ?? context.result;
447
- },
448
- validate: validateNoArgs,
449
- };
450
- const itsExpression$1 = {
451
- name: 'its',
452
- category: 'Reference',
453
- evaluatesTo: 'Any',
454
- async evaluate(context) {
455
- return context.it ?? context.result;
456
- },
457
- validate: validateNoArgs,
458
- };
459
- const resultExpression = {
460
- name: 'result',
461
- category: 'Reference',
462
- evaluatesTo: 'Any',
463
- async evaluate(context) {
464
- return context.result ?? context.it;
465
- },
466
- validate: validateNoArgs,
467
- };
468
- const querySelectorExpression = {
469
- name: 'querySelector',
470
- category: 'Reference',
471
- evaluatesTo: 'Element',
472
- async evaluate(_context, ...args) {
473
- const [selector] = args;
474
- if (typeof selector !== 'string') {
475
- throw new Error('querySelector requires a string selector');
476
- }
477
- return document.querySelector(selector);
478
- },
479
- validate(args) {
480
- return validateSingleStringArg(args, 'querySelector', 'selector');
481
- },
482
- };
483
- const querySelectorAllExpression = {
484
- name: 'querySelectorAll',
485
- category: 'Reference',
486
- evaluatesTo: 'Array',
487
- async evaluate(_context, ...args) {
488
- const selector = args[0];
489
- if (typeof selector !== 'string') {
490
- throw new Error('querySelectorAll requires a string selector');
491
- }
492
- const nodeList = document.querySelectorAll(selector);
493
- return Array.from(nodeList);
494
- },
495
- validate(args) {
496
- return validateSingleStringArg(args, 'querySelectorAll', 'selector');
497
- },
498
- };
499
- const idExpression = {
500
- name: 'getElementById',
501
- category: 'Reference',
502
- evaluatesTo: 'Element',
503
- async evaluate(_context, ...args) {
504
- const id = args[0];
505
- if (typeof id !== 'string') {
506
- throw new Error('getElementById requires a string ID');
507
- }
508
- return document.getElementById(id);
509
- },
510
- validate(args) {
511
- return validateSingleStringArg(args, 'getElementById', 'ID');
512
- },
513
- };
514
- const classExpression = {
515
- name: 'getElementsByClassName',
516
- category: 'Reference',
517
- evaluatesTo: 'Array',
518
- async evaluate(_context, ...args) {
519
- const className = args[0];
520
- if (typeof className !== 'string') {
521
- throw new Error('getElementsByClassName requires a string class name');
522
- }
523
- const collection = document.getElementsByClassName(className);
524
- return Array.from(collection);
525
- },
526
- validate(args) {
527
- return validateSingleStringArg(args, 'getElementsByClassName', 'className');
528
- },
529
- };
530
- const closestExpression = {
531
- name: 'closest',
532
- category: 'Reference',
533
- evaluatesTo: 'Element',
534
- async evaluate(context, ...args) {
535
- let selector = args[0];
536
- if (selector && typeof selector === 'object' && 'type' in selector) {
537
- const node = selector;
538
- if (node.type === 'identifier' && node.name) {
539
- selector = node.name;
540
- }
541
- else if (node.type === 'literal' && typeof node.value === 'string') {
542
- selector = node.value;
543
- }
544
- }
545
- if (typeof selector !== 'string') {
546
- throw new Error('closest requires a string selector');
547
- }
548
- const start = args.length > 1 ? args[1] : context.me;
549
- if (!(start instanceof Element)) {
550
- return null;
551
- }
552
- return start.closest(selector);
553
- },
554
- validate(args) {
555
- if (args.length !== 1 && args.length !== 2) {
556
- return 'closest requires a selector and, optionally, the element to start from';
557
- }
558
- const arg = args[0];
559
- if (typeof arg === 'string')
560
- return null;
561
- if (arg && typeof arg === 'object' && 'type' in arg) {
562
- const node = arg;
563
- if (node.type === 'identifier' || node.type === 'literal')
564
- return null;
565
- }
566
- return 'closest selector must be a string or identifier';
567
- },
568
- };
569
- const parentExpression = {
570
- name: 'parent',
571
- category: 'Reference',
572
- evaluatesTo: 'Element',
573
- async evaluate(context) {
574
- if (!context.me) {
575
- return null;
576
- }
577
- return context.me.parentElement;
578
- },
579
- validate: validateNoArgs,
580
- };
581
- const windowExpression = {
582
- name: 'window',
583
- category: 'Reference',
584
- evaluatesTo: 'Object',
585
- async evaluate(_context) {
586
- return window;
587
- },
588
- validate: validateNoArgs,
589
- };
590
- const documentExpression = {
591
- name: 'document',
592
- category: 'Reference',
593
- evaluatesTo: 'Object',
594
- async evaluate(_context) {
595
- return document;
596
- },
597
- validate: validateNoArgs,
598
- };
599
- const elementWithSelectorExpression = {
600
- name: 'elementWithSelector',
601
- category: 'Reference',
602
- evaluatesTo: 'Array',
603
- async evaluate(context, ...args) {
604
- const selector = args[0];
605
- if (typeof selector !== 'string') {
606
- throw new Error('Selector must be a string');
607
- }
608
- const doc = context?.me?.ownerDocument ??
609
- (typeof document !== 'undefined' ? document : null);
610
- if (!doc) {
611
- throw new Error('DOM not available - cannot resolve element selector');
612
- }
613
- const elements = doc.querySelectorAll(selector);
614
- return Array.from(elements);
615
- },
616
- validate(args) {
617
- return validateSingleStringArg(args, 'elementWithSelector', 'selector');
618
- },
619
- };
620
- function readStyleValue(target, property) {
621
- if (property.startsWith('computed-')) {
622
- const cssProperty = property.substring(9);
623
- return getComputedStyle(target).getPropertyValue(cssProperty) || '';
624
- }
625
- const camel = property.replace(/-([a-z])/g, (_m, c) => c.toUpperCase());
626
- return target.style[camel];
627
- }
628
- const styleRefExpression = {
629
- name: 'styleRef',
630
- category: 'Reference',
631
- evaluatesTo: 'String',
632
- async evaluate(context, ...args) {
633
- const property = args[0];
634
- const element = args[1];
635
- if (typeof property !== 'string') {
636
- throw new Error('StyleRef requires a string property name');
637
- }
638
- const target = element || context.me;
639
- if (!target || !(target instanceof HTMLElement)) {
640
- return undefined;
641
- }
642
- return readStyleValue(target, property);
643
- },
644
- validate(args) {
645
- return (validateArgRange(args, 1, 2, 'styleRef', 'property, optional element') ??
646
- validateArgIsString(args, 0, 'styleRef', 'property') ??
647
- (args.length === 2 && args[1] && typeof args[1] !== 'object'
648
- ? 'styleRef element must be an HTMLElement'
649
- : null));
650
- },
651
- };
652
- const possessiveStyleRefExpression = {
653
- name: 'possessiveStyleRef',
654
- category: 'Reference',
655
- evaluatesTo: 'String',
656
- async evaluate(context, ...args) {
657
- const possessor = args[0];
658
- const property = args[1];
659
- if (typeof possessor !== 'string' || typeof property !== 'string') {
660
- throw new Error('Possessive styleRef requires possessor and property strings');
661
- }
662
- let target = null;
663
- if (possessor === 'my' && context.me) {
664
- target = context.me instanceof HTMLElement ? context.me : null;
665
- }
666
- else if (possessor === 'its' && context.it) {
667
- target = context.it instanceof HTMLElement ? context.it : null;
668
- }
669
- if (!target) {
670
- return undefined;
671
- }
672
- return readStyleValue(target, property);
673
- },
674
- validate(args) {
675
- return (validateArgCount(args, 2, 'possessiveStyleRef', 'possessor, property') ??
676
- validateArgIsString(args, 0, 'possessiveStyleRef', 'possessor') ??
677
- validateArgIsString(args, 1, 'possessiveStyleRef', 'property'));
678
- },
679
- };
680
- const ofStyleRefExpression = {
681
- name: 'ofStyleRef',
682
- category: 'Reference',
683
- evaluatesTo: 'String',
684
- async evaluate(context, ...args) {
685
- const property = args[0];
686
- const reference = args[1];
687
- if (typeof property !== 'string' || typeof reference !== 'string') {
688
- throw new Error('Of styleRef requires property and reference strings');
689
- }
690
- let target = null;
691
- if (reference === 'me' && context.me) {
692
- target = context.me instanceof HTMLElement ? context.me : null;
693
- }
694
- else if (reference === 'it' && context.it) {
695
- target = context.it instanceof HTMLElement ? context.it : null;
696
- }
697
- if (!target) {
698
- return undefined;
699
- }
700
- return readStyleValue(target, property);
701
- },
702
- validate(args) {
703
- return (validateArgCount(args, 2, 'ofStyleRef', 'property, reference') ??
704
- validateArgIsString(args, 0, 'ofStyleRef', 'property') ??
705
- validateArgIsString(args, 1, 'ofStyleRef', 'reference'));
706
- },
707
- };
708
- const referencesExpressions = {
709
- me: meExpression,
710
- you: youExpression,
711
- it: itExpression,
712
- its: itsExpression$1,
713
- result: resultExpression,
714
- querySelector: querySelectorExpression,
715
- querySelectorAll: querySelectorAllExpression,
716
- getElementById: idExpression,
717
- getElementsByClassName: classExpression,
718
- closest: closestExpression,
719
- parent: parentExpression,
720
- window: windowExpression,
721
- document: documentExpression,
722
- elementWithSelector: elementWithSelectorExpression,
723
- styleRef: styleRefExpression,
724
- possessiveStyleRef: possessiveStyleRefExpression,
725
- ofStyleRef: ofStyleRefExpression,
726
- };
727
-
728
- function createValidationError(type, message, path, suggestions = []) {
729
- return {
730
- type,
731
- message,
732
- suggestions,
733
- ...(path && { path }),
734
- };
735
- }
736
- const isProduction = typeof process !== 'undefined' ? process.env.NODE_ENV === 'production' : false;
737
- const skipValidation = isProduction ||
738
- (typeof process !== 'undefined' && process.env.HYPERFIXI_SKIP_VALIDATION === 'true') ||
739
- (typeof globalThis !== 'undefined' && globalThis.HYPERFIXI_SKIP_VALIDATION === 'true');
740
- let addDescribeToValidator;
741
- function createPassthroughValidator() {
742
- return addDescribeToValidator({
743
- validate: (value) => ({
744
- success: true,
745
- data: value,
746
- }),
747
- });
748
- }
749
- function createStringValidator(options = {}) {
750
- if (skipValidation) {
751
- return createPassthroughValidator();
752
- }
753
- return addDescribeToValidator({
754
- validate: (value) => {
755
- if (options.optional && (value === undefined || value === null)) {
756
- return { success: true, data: undefined };
757
- }
758
- if (typeof value !== 'string') {
759
- return {
760
- success: false,
761
- error: createValidationError('type-mismatch', `Expected string, received ${typeof value}`),
762
- };
763
- }
764
- if (options.minLength !== undefined && value.length < options.minLength) {
765
- return {
766
- success: false,
767
- error: createValidationError('runtime-error', `String must be at least ${options.minLength} characters long`),
768
- };
769
- }
770
- if (options.maxLength !== undefined && value.length > options.maxLength) {
771
- return {
772
- success: false,
773
- error: createValidationError('runtime-error', `String must be at most ${options.maxLength} characters long`),
774
- };
775
- }
776
- if (options.pattern && !options.pattern.test(value)) {
777
- if (options.pattern.source.startsWith('^') && options.pattern.source.endsWith('$')) {
778
- const expected = options.pattern.source.slice(1, -1);
779
- return {
780
- success: false,
781
- error: createValidationError('runtime-error', `Expected "${expected}", received "${value}"`),
782
- };
783
- }
784
- return {
785
- success: false,
786
- error: createValidationError('missing-argument', `String does not match required pattern`),
787
- };
788
- }
789
- return { success: true, data: value };
790
- },
791
- ...(options.description && { description: options.description }),
792
- });
793
- }
794
- function createObjectValidator(fields, options) {
795
- if (skipValidation) {
796
- return createPassthroughValidator();
797
- }
798
- const validator = addDescribeToValidator({
799
- validate: (value) => {
800
- if (typeof value !== 'object' || value === null || Array.isArray(value)) {
801
- return {
802
- success: false,
803
- error: createValidationError('type-mismatch', `Expected object, received ${typeof value}`),
804
- };
805
- }
806
- const obj = value;
807
- const result = {};
808
- if (options?.strict) {
809
- const allowedKeys = Object.keys(fields);
810
- const actualKeys = Object.keys(obj);
811
- const extraKeys = actualKeys.filter(key => !allowedKeys.includes(key));
812
- if (extraKeys.length > 0) {
813
- return {
814
- success: false,
815
- error: createValidationError('runtime-error', `Unexpected properties: ${extraKeys.join(', ')}`),
816
- };
817
- }
818
- }
819
- for (const [fieldName, validator] of Object.entries(fields)) {
820
- const fieldValue = obj[fieldName];
821
- const fieldExists = fieldName in obj;
822
- if (!fieldExists && !validator._isOptional) {
823
- return {
824
- success: false,
825
- error: createValidationError('missing-argument', `Required field "${fieldName}" is missing`, fieldName),
826
- };
827
- }
828
- const fieldResult = validator.validate(fieldValue);
829
- if (!fieldResult.success) {
830
- const errorPath = fieldResult.error.path
831
- ? `${fieldName}.${fieldResult.error.path}`
832
- : fieldName;
833
- return {
834
- success: false,
835
- error: createValidationError('validation-error', fieldResult.error.message || `Field "${fieldName}" validation failed`, errorPath),
836
- };
837
- }
838
- if (fieldResult.data !== undefined) {
839
- result[fieldName] = fieldResult.data;
840
- }
841
- }
842
- return { success: true, data: result };
843
- },
844
- });
845
- validator.strict = () => createObjectValidator(fields, { strict: true });
846
- return validator;
847
- }
848
- function createArrayValidator(itemValidator) {
849
- if (skipValidation) {
850
- return createPassthroughValidator();
851
- }
852
- return addDescribeToValidator({
853
- validate: (value) => {
854
- if (!Array.isArray(value)) {
855
- return {
856
- success: false,
857
- error: createValidationError('type-mismatch', `Expected array, received ${typeof value}`),
858
- };
859
- }
860
- const result = [];
861
- for (let i = 0; i < value.length; i++) {
862
- const itemResult = itemValidator.validate(value[i]);
863
- if (!itemResult.success) {
864
- const errorPath = itemResult.error.path ? `${i}.${itemResult.error.path}` : `${i}`;
865
- return {
866
- success: false,
867
- error: createValidationError('runtime-error', itemResult.error.message, errorPath),
868
- };
869
- }
870
- result.push(itemResult.data);
871
- }
872
- return { success: true, data: result };
873
- },
874
- });
875
- }
876
- function createTupleValidator(validators) {
877
- if (skipValidation) {
878
- return createPassthroughValidator();
879
- }
880
- return addDescribeToValidator({
881
- validate: (value) => {
882
- if (!Array.isArray(value)) {
883
- return {
884
- success: false,
885
- error: createValidationError('type-mismatch', `Expected array, received ${typeof value}`),
886
- };
887
- }
888
- if (value.length !== validators.length) {
889
- return {
890
- success: false,
891
- error: createValidationError('runtime-error', `Expected tuple of length ${validators.length}, received length ${value.length}`),
892
- };
893
- }
894
- const result = [];
895
- for (let i = 0; i < validators.length; i++) {
896
- const itemResult = validators[i].validate(value[i]);
897
- if (!itemResult.success) {
898
- const errorPath = itemResult.error.path ? `${i}.${itemResult.error.path}` : `${i}`;
899
- return {
900
- success: false,
901
- error: createValidationError('runtime-error', itemResult.error.message, errorPath),
902
- };
903
- }
904
- result.push(itemResult.data);
905
- }
906
- return {
907
- success: true,
908
- data: result,
909
- };
910
- },
911
- });
912
- }
913
- function createUnionValidator(validators) {
914
- if (skipValidation) {
915
- return createPassthroughValidator();
916
- }
917
- return addDescribeToValidator({
918
- validate: (value) => {
919
- const errors = [];
920
- for (const validator of validators) {
921
- const result = validator.validate(value);
922
- if (result.success) {
923
- return result;
924
- }
925
- errors.push(result.error.message);
926
- }
927
- return {
928
- success: false,
929
- error: createValidationError('type-mismatch', 'Value does not match any union type'),
930
- };
931
- },
932
- });
933
- }
934
- function createLiteralValidator(literalValue) {
935
- if (skipValidation) {
936
- return createPassthroughValidator();
937
- }
938
- return addDescribeToValidator({
939
- validate: (value) => {
940
- if (value === literalValue) {
941
- return { success: true, data: value };
942
- }
943
- return {
944
- success: false,
945
- error: createValidationError('runtime-error', `Expected ${JSON.stringify(literalValue)}, received ${JSON.stringify(value)}`),
946
- };
947
- },
948
- });
949
- }
950
- function createNumberValidator(options = {}) {
951
- if (skipValidation) {
952
- return createPassthroughValidator();
953
- }
954
- return addDescribeToValidator({
955
- validate: (value) => {
956
- const num = Number(value);
957
- if (isNaN(num)) {
958
- return {
959
- success: false,
960
- error: createValidationError('type-mismatch', `Expected number, received ${typeof value}`),
961
- };
962
- }
963
- if (options.min !== undefined && num < options.min) {
964
- return {
965
- success: false,
966
- error: createValidationError('runtime-error', `Number must be at least ${options.min}`),
967
- };
968
- }
969
- if (options.max !== undefined && num > options.max) {
970
- return {
971
- success: false,
972
- error: createValidationError('runtime-error', `Number must be at most ${options.max}`),
973
- };
974
- }
975
- return { success: true, data: num };
976
- },
977
- });
978
- }
979
- function createBooleanValidator() {
980
- if (skipValidation) {
981
- return createPassthroughValidator();
982
- }
983
- return addDescribeToValidator({
984
- validate: (value) => {
985
- if (typeof value !== 'boolean') {
986
- return {
987
- success: false,
988
- error: createValidationError('type-mismatch', `Expected boolean, received ${typeof value}`),
989
- };
990
- }
991
- return { success: true, data: value };
992
- },
993
- });
994
- }
995
- function createCustomValidator(validator, errorMessage = 'Custom validation failed') {
996
- if (skipValidation) {
997
- return createPassthroughValidator();
998
- }
999
- return addDescribeToValidator({
1000
- validate: (value) => {
1001
- if (validator(value)) {
1002
- return { success: true, data: value };
1003
- }
1004
- return {
1005
- success: false,
1006
- error: createValidationError('runtime-error', errorMessage),
1007
- };
1008
- },
1009
- });
1010
- }
1011
- addDescribeToValidator = function (validator) {
1012
- if (!validator.describe) {
1013
- validator.describe = function (description) {
1014
- this.description = description;
1015
- return this;
1016
- };
1017
- }
1018
- if (!validator.safeParse) {
1019
- validator.safeParse = function (value) {
1020
- const result = this.validate(value);
1021
- if (result.success) {
1022
- return { success: true, data: result.data };
1023
- }
1024
- else {
1025
- return {
1026
- success: false,
1027
- error: { errors: result.error ? [result.error] : [] },
1028
- };
1029
- }
1030
- };
1031
- }
1032
- if (!validator.parse) {
1033
- validator.parse = function (value) {
1034
- const result = this.validate(value);
1035
- if (result.success && result.data !== undefined) {
1036
- return result.data;
1037
- }
1038
- throw new Error(result.error?.message || 'Validation failed');
1039
- };
1040
- }
1041
- if (!validator.optional) {
1042
- validator.optional = function () {
1043
- const originalValidate = this.validate.bind(this);
1044
- const optionalValidator = {
1045
- ...this,
1046
- _isOptional: true,
1047
- validate: (value) => {
1048
- if (value === undefined || value === null) {
1049
- return { success: true, data: undefined };
1050
- }
1051
- return originalValidate(value);
1052
- },
1053
- };
1054
- return addDescribeToValidator(optionalValidator);
1055
- };
1056
- }
1057
- if (!validator.min) {
1058
- validator.min = function (minLength) {
1059
- const originalValidate = this.validate.bind(this);
1060
- const minValidator = {
1061
- ...this,
1062
- validate: (value) => {
1063
- const result = originalValidate(value);
1064
- if (!result.success) {
1065
- return result;
1066
- }
1067
- if (typeof result.data === 'string' && result.data.length < minLength) {
1068
- return {
1069
- success: false,
1070
- error: createValidationError('runtime-error', `String must be at least ${minLength} characters long`),
1071
- };
1072
- }
1073
- return result;
1074
- },
1075
- };
1076
- return addDescribeToValidator(minValidator);
1077
- };
1078
- }
1079
- if (!validator.max) {
1080
- validator.max = function (maxLength) {
1081
- const originalValidate = this.validate.bind(this);
1082
- const maxValidator = {
1083
- ...this,
1084
- validate: (value) => {
1085
- const result = originalValidate(value);
1086
- if (!result.success) {
1087
- return result;
1088
- }
1089
- if (typeof result.data === 'string' && result.data.length > maxLength) {
1090
- return {
1091
- success: false,
1092
- error: createValidationError('runtime-error', `String must be at most ${maxLength} characters long`),
1093
- };
1094
- }
1095
- return result;
1096
- },
1097
- };
1098
- return addDescribeToValidator(maxValidator);
1099
- };
1100
- }
1101
- if (!validator.default) {
1102
- validator.default = function (defaultValue) {
1103
- const originalValidate = this.validate.bind(this);
1104
- const defaultValidator = {
1105
- ...this,
1106
- _defaultValue: defaultValue,
1107
- _hasDefault: true,
1108
- validate: (value) => {
1109
- if (value === undefined) {
1110
- return { success: true, data: defaultValue };
1111
- }
1112
- return originalValidate(value);
1113
- },
1114
- };
1115
- return addDescribeToValidator(defaultValidator);
1116
- };
1117
- }
1118
- if (!validator.rest) {
1119
- validator.rest = function (_restValidator) {
1120
- return this;
1121
- };
1122
- }
1123
- if (!validator.refine) {
1124
- validator.refine = function (refineFn, errorMessage) {
1125
- const originalValidate = this.validate.bind(this);
1126
- const refinedValidator = {
1127
- ...this,
1128
- validate: (value) => {
1129
- const result = originalValidate(value);
1130
- if (!result.success) {
1131
- return result;
1132
- }
1133
- if (!refineFn(result.data)) {
1134
- return {
1135
- success: false,
1136
- error: createValidationError('runtime-error', errorMessage || 'Refinement validation failed'),
1137
- };
1138
- }
1139
- return result;
1140
- },
1141
- };
1142
- return addDescribeToValidator(refinedValidator);
1143
- };
1144
- }
1145
- return new Proxy(validator, {
1146
- get(target, prop, receiver) {
1147
- if (prop in target) {
1148
- return Reflect.get(target, prop, receiver);
1149
- }
1150
- if (typeof prop === 'string' &&
1151
- !prop.startsWith('_') &&
1152
- prop !== 'constructor' &&
1153
- prop !== 'validate' &&
1154
- prop !== 'then') {
1155
- return function (..._args) {
1156
- return receiver;
1157
- };
1158
- }
1159
- return Reflect.get(target, prop, receiver);
1160
- },
1161
- });
1162
- };
1163
- function createRecordValidator(keyValidator, valueValidator) {
1164
- if (skipValidation) {
1165
- return createPassthroughValidator();
1166
- }
1167
- return addDescribeToValidator({
1168
- validate: (value) => {
1169
- if (typeof value !== 'object' || value === null || Array.isArray(value)) {
1170
- return {
1171
- success: false,
1172
- error: createValidationError('type-mismatch', `Expected record object, received ${typeof value}`),
1173
- };
1174
- }
1175
- const obj = value;
1176
- const result = {};
1177
- for (const [key, val] of Object.entries(obj)) {
1178
- const keyResult = keyValidator.validate(key);
1179
- if (!keyResult.success) {
1180
- return {
1181
- success: false,
1182
- error: createValidationError('invalid-argument', `Invalid key "${key}": ${keyResult.error.message}`, key),
1183
- };
1184
- }
1185
- const valueResult = valueValidator.validate(val);
1186
- if (!valueResult.success) {
1187
- const errorPath = valueResult.error.path ? `${key}.${valueResult.error.path}` : key;
1188
- return {
1189
- success: false,
1190
- error: createValidationError('runtime-error', valueResult.error.message, errorPath),
1191
- };
1192
- }
1193
- result[key] = valueResult.data;
1194
- }
1195
- return { success: true, data: result };
1196
- },
1197
- });
1198
- }
1199
- function createEnumValidator(values) {
1200
- if (skipValidation) {
1201
- return createPassthroughValidator();
1202
- }
1203
- return addDescribeToValidator({
1204
- validate: (value) => {
1205
- if (typeof value !== 'string' && typeof value !== 'number' && typeof value !== 'boolean') {
1206
- return {
1207
- success: false,
1208
- error: createValidationError('type-mismatch', `Expected string, received ${typeof value}`),
1209
- };
1210
- }
1211
- if (!values.includes(value)) {
1212
- return {
1213
- success: false,
1214
- error: createValidationError('runtime-error', `Expected one of [${values.join(', ')}], received "${value}"`),
1215
- };
1216
- }
1217
- return { success: true, data: value };
1218
- },
1219
- });
1220
- }
1221
- const v = {
1222
- string: (options) => createStringValidator(options || {}),
1223
- number: (options) => createNumberValidator(options || {}),
1224
- boolean: () => createBooleanValidator(),
1225
- object: (fields) => createObjectValidator(fields),
1226
- array: (itemValidator) => createArrayValidator(itemValidator),
1227
- tuple: (validators) => createTupleValidator(validators),
1228
- union: (validators) => createUnionValidator(validators),
1229
- literal: (value) => createLiteralValidator(value),
1230
- custom: (validator, errorMessage) => createCustomValidator(validator, errorMessage),
1231
- record: (keyValidator, valueValidator) => createRecordValidator(keyValidator, valueValidator),
1232
- enum: (values) => createEnumValidator(values),
1233
- function: () => createCustomValidator(value => typeof value === 'function', 'Expected function'),
1234
- unknown: () => createPassthroughValidator(),
1235
- any: () => createPassthroughValidator(),
1236
- null: () => createCustomValidator(value => value === null, 'Expected null'),
1237
- undefined: () => createCustomValidator(value => value === undefined, 'Expected undefined'),
1238
- instanceOf: (constructor) => createCustomValidator(value => value instanceof constructor, `Expected instance of ${constructor.name}`),
1239
- instanceof: (constructor) => createCustomValidator(value => value instanceof constructor, `Expected instance of ${constructor.name}`),
1240
- };
1241
-
1242
- class LRUCache {
1243
- constructor(maxSize = 100, ttl = 5000) {
1244
- this.maxSize = maxSize;
1245
- this.ttl = ttl;
1246
- this.cache = new Map();
1247
- this.accessOrder = new Map();
1248
- this.accessCounter = 0;
1249
- }
1250
- get(key) {
1251
- const entry = this.cache.get(key);
1252
- if (!entry)
1253
- return undefined;
1254
- if (Date.now() - entry.timestamp > this.ttl) {
1255
- this.delete(key);
1256
- return undefined;
1257
- }
1258
- entry.accessCount++;
1259
- this.accessOrder.set(key, ++this.accessCounter);
1260
- return entry.result;
1261
- }
1262
- set(key, value) {
1263
- if (this.cache.size >= this.maxSize && !this.cache.has(key)) {
1264
- this.evictLRU();
1265
- }
1266
- const entry = {
1267
- result: value,
1268
- timestamp: Date.now(),
1269
- accessCount: 1,
1270
- };
1271
- this.cache.set(key, entry);
1272
- this.accessOrder.set(key, ++this.accessCounter);
1273
- }
1274
- delete(key) {
1275
- this.accessOrder.delete(key);
1276
- return this.cache.delete(key);
1277
- }
1278
- clear() {
1279
- this.cache.clear();
1280
- this.accessOrder.clear();
1281
- this.accessCounter = 0;
1282
- }
1283
- size() {
1284
- return this.cache.size;
1285
- }
1286
- evictLRU() {
1287
- let lruKey;
1288
- let lruAccessOrder = Infinity;
1289
- for (const [key, accessOrder] of this.accessOrder) {
1290
- if (accessOrder < lruAccessOrder) {
1291
- lruAccessOrder = accessOrder;
1292
- lruKey = key;
1293
- }
1294
- }
1295
- if (lruKey !== undefined) {
1296
- this.delete(lruKey);
1297
- }
1298
- }
1299
- getStats() {
1300
- const entries = Array.from(this.cache.values());
1301
- const now = Date.now();
1302
- return {
1303
- size: this.cache.size,
1304
- maxSize: this.maxSize,
1305
- hitRate: entries.length > 0 ? entries.filter(e => e.accessCount > 1).length / entries.length : 0,
1306
- avgAge: entries.length > 0
1307
- ? entries.reduce((sum, e) => sum + (now - e.timestamp), 0) / entries.length
1308
- : 0,
1309
- totalAccesses: entries.reduce((sum, e) => sum + e.accessCount, 0),
1310
- };
1311
- }
1312
- }
1313
- class HyperscriptCache {
1314
- constructor() {
1315
- this.domQueryCache = new LRUCache(200, 3000);
1316
- this.exprResultCache = new LRUCache(500, 2000);
1317
- this.cssMatchCache = new LRUCache(100, 5000);
1318
- this.formValueCache = new LRUCache(50, 1000);
1319
- this.hits = 0;
1320
- this.misses = 0;
1321
- }
1322
- querySelector(selector) {
1323
- const cacheKey = `querySelector:${selector}`;
1324
- const cached = this.domQueryCache.get(cacheKey);
1325
- if (cached !== undefined) {
1326
- this.hits++;
1327
- return cached;
1328
- }
1329
- this.misses++;
1330
- const result = document.querySelector(selector);
1331
- this.domQueryCache.set(cacheKey, result);
1332
- return result;
1333
- }
1334
- querySelectorAll(selector) {
1335
- const cacheKey = `querySelectorAll:${selector}`;
1336
- const cached = this.domQueryCache.get(cacheKey);
1337
- if (cached !== undefined) {
1338
- this.hits++;
1339
- return cached;
1340
- }
1341
- this.misses++;
1342
- const result = Array.from(document.querySelectorAll(selector));
1343
- this.domQueryCache.set(cacheKey, result);
1344
- return result;
1345
- }
1346
- getElementById(id) {
1347
- const cacheKey = `getElementById:${id}`;
1348
- const cached = this.domQueryCache.get(cacheKey);
1349
- if (cached !== undefined) {
1350
- this.hits++;
1351
- return cached;
1352
- }
1353
- this.misses++;
1354
- const result = document.getElementById(id);
1355
- this.domQueryCache.set(cacheKey, result);
1356
- return result;
1357
- }
1358
- getElementsByClassName(className) {
1359
- const cacheKey = `getElementsByClassName:${className}`;
1360
- const cached = this.domQueryCache.get(cacheKey);
1361
- if (cached !== undefined) {
1362
- this.hits++;
1363
- return cached;
1364
- }
1365
- this.misses++;
1366
- const result = Array.from(document.getElementsByClassName(className));
1367
- this.domQueryCache.set(cacheKey, result);
1368
- return result;
1369
- }
1370
- matches(element, selector) {
1371
- const elementId = this.getElementCacheKey(element);
1372
- const cacheKey = `matches:${elementId}:${selector}`;
1373
- const cached = this.cssMatchCache.get(cacheKey);
1374
- if (cached !== undefined) {
1375
- this.hits++;
1376
- return cached;
1377
- }
1378
- this.misses++;
1379
- const result = element.matches(selector);
1380
- this.cssMatchCache.set(cacheKey, result);
1381
- return result;
1382
- }
1383
- getExpressionResult(exprKey) {
1384
- const cached = this.exprResultCache.get(exprKey);
1385
- if (cached !== undefined) {
1386
- this.hits++;
1387
- return cached;
1388
- }
1389
- this.misses++;
1390
- return undefined;
1391
- }
1392
- setExpressionResult(exprKey, result) {
1393
- this.exprResultCache.set(exprKey, result);
1394
- }
1395
- getFormValue(form) {
1396
- const formId = this.getElementCacheKey(form);
1397
- const cacheKey = `formValue:${formId}`;
1398
- const cached = this.formValueCache.get(cacheKey);
1399
- if (cached !== undefined) {
1400
- this.hits++;
1401
- return cached;
1402
- }
1403
- this.misses++;
1404
- return undefined;
1405
- }
1406
- setFormValue(form, value) {
1407
- const formId = this.getElementCacheKey(form);
1408
- const cacheKey = `formValue:${formId}`;
1409
- this.formValueCache.set(cacheKey, value);
1410
- }
1411
- invalidateElementCache(element) {
1412
- const elementId = this.getElementCacheKey(element);
1413
- for (const cache of [this.domQueryCache, this.cssMatchCache, this.formValueCache]) {
1414
- for (const key of Array.from(cache['cache'].keys())) {
1415
- if (typeof key === 'string' && key.includes(elementId)) {
1416
- cache.delete(key);
1417
- }
1418
- }
1419
- }
1420
- }
1421
- invalidateAll() {
1422
- this.domQueryCache.clear();
1423
- this.exprResultCache.clear();
1424
- this.cssMatchCache.clear();
1425
- this.formValueCache.clear();
1426
- this.hits = 0;
1427
- this.misses = 0;
1428
- }
1429
- getElementCacheKey(element) {
1430
- if (element.id)
1431
- return `#${element.id}`;
1432
- const classes = Array.from(element.classList).sort().join('.');
1433
- const position = this.getElementPosition(element);
1434
- return `${element.tagName.toLowerCase()}${classes ? '.' + classes : ''}@${position}`;
1435
- }
1436
- getElementPosition(element) {
1437
- const siblings = Array.from(element.parentElement?.children || []);
1438
- const index = siblings.indexOf(element);
1439
- return `${index}`;
1440
- }
1441
- getPerformanceStats() {
1442
- const total = this.hits + this.misses;
1443
- const hitRate = total > 0 ? (this.hits / total) * 100 : 0;
1444
- return {
1445
- hits: this.hits,
1446
- misses: this.misses,
1447
- hitRate: Math.round(hitRate * 100) / 100,
1448
- domQueryCache: this.domQueryCache.getStats(),
1449
- exprResultCache: this.exprResultCache.getStats(),
1450
- cssMatchCache: this.cssMatchCache.getStats(),
1451
- formValueCache: this.formValueCache.getStats(),
1452
- };
1453
- }
1454
- cleanup() {
1455
- const now = Date.now();
1456
- [this.domQueryCache, this.exprResultCache, this.cssMatchCache, this.formValueCache].forEach(cache => {
1457
- const entries = Array.from(cache['cache'].entries());
1458
- entries.forEach(([key, entry]) => {
1459
- if (now - entry.timestamp > cache['ttl']) {
1460
- cache.delete(key);
1461
- }
1462
- });
1463
- });
1464
- }
1465
- }
1466
- const globalCache = new HyperscriptCache();
1467
- if (typeof window !== 'undefined') {
1468
- setInterval(() => {
1469
- globalCache.cleanup();
1470
- }, 10000);
1471
- }
1472
-
1473
- var TokenKind;
1474
- (function (TokenKind) {
1475
- TokenKind["IDENTIFIER"] = "identifier";
1476
- TokenKind["STRING"] = "string";
1477
- TokenKind["NUMBER"] = "number";
1478
- TokenKind["SELECTOR"] = "selector";
1479
- TokenKind["OPERATOR"] = "operator";
1480
- TokenKind["TIME"] = "time";
1481
- TokenKind["TEMPLATE"] = "template";
1482
- TokenKind["COMMENT"] = "comment";
1483
- TokenKind["SYMBOL"] = "symbol";
1484
- TokenKind["UNKNOWN"] = "unknown";
1485
- })(TokenKind || (TokenKind = {}));
1486
-
1487
- class PerformanceTracker {
1488
- constructor() {
1489
- this.metrics = {
1490
- tokenizationTime: 0,
1491
- evaluationTime: 0,
1492
- cacheHitRate: 0,
1493
- memoryUsage: 0,
1494
- domOperations: 0,
1495
- };
1496
- this.startTimes = new Map();
1497
- }
1498
- startTimer(operation) {
1499
- this.startTimes.set(operation, performance.now());
1500
- }
1501
- endTimer(operation) {
1502
- const startTime = this.startTimes.get(operation);
1503
- if (startTime) {
1504
- const duration = performance.now() - startTime;
1505
- this.startTimes.delete(operation);
1506
- return duration;
1507
- }
1508
- return 0;
1509
- }
1510
- recordTokenization(duration) {
1511
- this.metrics.tokenizationTime += duration;
1512
- }
1513
- recordEvaluation(duration) {
1514
- this.metrics.evaluationTime += duration;
1515
- }
1516
- updateCacheMetrics() {
1517
- const cacheStats = globalCache.getPerformanceStats();
1518
- this.metrics.cacheHitRate = cacheStats.hitRate;
1519
- }
1520
- getMetrics() {
1521
- this.updateCacheMetrics();
1522
- return { ...this.metrics };
1523
- }
1524
- reset() {
1525
- this.metrics = {
1526
- tokenizationTime: 0,
1527
- evaluationTime: 0,
1528
- cacheHitRate: 0,
1529
- memoryUsage: 0,
1530
- domOperations: 0,
1531
- };
1532
- }
1533
- }
1534
- const performanceTracker = new PerformanceTracker();
1535
- function matchesWithCache(element, selector) {
1536
- return globalCache.matches(element, selector);
1537
- }
1538
- function performCleanup() {
1539
- globalCache.cleanup();
1540
- const metrics = performanceTracker.getMetrics();
1541
- if (metrics.memoryUsage > 50 * 1024 * 1024) {
1542
- performanceTracker.reset();
1543
- }
1544
- }
1545
- let cleanupInterval = null;
1546
- function enableAutoCleanup(intervalMs = 30000) {
1547
- if (cleanupInterval) {
1548
- clearInterval(cleanupInterval);
1549
- }
1550
- cleanupInterval = setInterval(performCleanup, intervalMs);
1551
- }
1552
- if (typeof window !== 'undefined') {
1553
- enableAutoCleanup();
1554
- }
1555
-
1556
- function toNumber(value, context) {
1557
- if (typeof value === 'number') {
1558
- if (!Number.isFinite(value)) {
1559
- throw new Error(`${context} must be a finite number, got ${value}`);
1560
- }
1561
- return value;
1562
- }
1563
- if (typeof value === 'string') {
1564
- const trimmed = value.trim();
1565
- if (trimmed === '') {
1566
- return 0;
1567
- }
1568
- const num = parseFloat(trimmed);
1569
- if (isNaN(num)) {
1570
- throw new Error(`${context} cannot be converted to number: "${value}"`);
1571
- }
1572
- return num;
1573
- }
1574
- if (typeof value === 'boolean') {
1575
- return value ? 1 : 0;
1576
- }
1577
- if (value === null || value === undefined) {
1578
- return 0;
1579
- }
1580
- if (typeof value === 'object' && value !== null) {
1581
- if (Array.isArray(value) && value.length === 1) {
1582
- const inner = value[0];
1583
- if (Array.isArray(inner)) {
1584
- throw new Error(`${context} is a nested array, cannot convert to number`);
1585
- }
1586
- return toNumber(inner, context);
1587
- }
1588
- const obj = value;
1589
- if (typeof obj.textContent === 'string' || 'value' in obj) {
1590
- const text = obj.value ?? obj.textContent;
1591
- if (text !== null && text !== undefined) {
1592
- const trimmed = String(text).trim();
1593
- if (trimmed === '')
1594
- return 0;
1595
- const num = parseFloat(trimmed);
1596
- if (!isNaN(num))
1597
- return num;
1598
- }
1599
- }
1600
- const primitive = value.valueOf();
1601
- if (typeof primitive === 'number' && Number.isFinite(primitive)) {
1602
- return primitive;
1603
- }
1604
- }
1605
- throw new Error(`${context} cannot be converted to number: ${typeof value}`);
1606
- }
1607
- function toNumberOrNull(value) {
1608
- if (typeof value === 'number') {
1609
- return Number.isFinite(value) ? value : null;
1610
- }
1611
- if (typeof value === 'string') {
1612
- const trimmed = value.trim();
1613
- if (trimmed === '')
1614
- return 0;
1615
- const num = parseFloat(trimmed);
1616
- return isNaN(num) ? null : num;
1617
- }
1618
- if (typeof value === 'boolean') {
1619
- return value ? 1 : 0;
1620
- }
1621
- if (value === null || value === undefined) {
1622
- return 0;
1623
- }
1624
- return null;
1625
- }
1626
- function ensureFinite(num, operation) {
1627
- if (!Number.isFinite(num)) {
1628
- if (Number.isNaN(num)) {
1629
- throw new Error(`${operation} resulted in non-finite value: NaN`);
1630
- }
1631
- throw new Error(`${operation} resulted in non-finite value: ${num > 0 ? 'Infinity' : '-Infinity'}`);
1632
- }
1633
- return num;
1634
- }
1635
- function canBeNumeric(value) {
1636
- try {
1637
- toNumber(value, '_');
1638
- return true;
1639
- }
1640
- catch {
1641
- return false;
1642
- }
1643
- }
1644
- function safeDivide(left, right, allowInfinity = true) {
1645
- if (right === 0) {
1646
- if (allowInfinity) {
1647
- return left === 0 ? NaN : left > 0 ? Infinity : -Infinity;
1648
- }
1649
- throw new Error('Division by zero');
1650
- }
1651
- return left / right;
1652
- }
1653
- function safeModulo(left, right) {
1654
- if (right === 0) {
1655
- throw new Error('Modulo by zero');
1656
- }
1657
- return left % right;
1658
- }
1659
-
1660
- function compareValues(left, right, operator) {
1661
- if (operator === '===') {
1662
- return left === right;
1663
- }
1664
- if (operator === '!==') {
1665
- return left !== right;
1666
- }
1667
- if (left == null || right == null) {
1668
- return compareNullish(left, right, operator);
1669
- }
1670
- const [leftVal, rightVal] = coerceToComparable(left, right);
1671
- switch (operator) {
1672
- case '>':
1673
- return leftVal > rightVal;
1674
- case '<':
1675
- return leftVal < rightVal;
1676
- case '>=':
1677
- return leftVal >= rightVal;
1678
- case '<=':
1679
- return leftVal <= rightVal;
1680
- case '==':
1681
- return compareEquality(left, right);
1682
- case '!=':
1683
- return !compareEquality(left, right);
1684
- default:
1685
- return false;
1686
- }
1687
- }
1688
- function compareNullish(left, right, operator) {
1689
- const leftIsNullish = left == null;
1690
- const rightIsNullish = right == null;
1691
- if (leftIsNullish && rightIsNullish) {
1692
- switch (operator) {
1693
- case '==':
1694
- case '>=':
1695
- case '<=':
1696
- return true;
1697
- case '!=':
1698
- case '>':
1699
- case '<':
1700
- return false;
1701
- default:
1702
- return false;
1703
- }
1704
- }
1705
- switch (operator) {
1706
- case '==':
1707
- return false;
1708
- case '!=':
1709
- return true;
1710
- case '>':
1711
- case '<':
1712
- case '>=':
1713
- case '<=':
1714
- return false;
1715
- default:
1716
- return false;
1717
- }
1718
- }
1719
- function compareEquality(left, right) {
1720
- if (left === right) {
1721
- return true;
1722
- }
1723
- if (typeof left === typeof right) {
1724
- if (typeof left === 'string') {
1725
- return left === right;
1726
- }
1727
- if (typeof left === 'number') {
1728
- return left === right;
1729
- }
1730
- return false;
1731
- }
1732
- if (typeof left === 'number' && typeof right === 'string') {
1733
- const rightNum = parseFloat(right);
1734
- return !isNaN(rightNum) && left === rightNum;
1735
- }
1736
- if (typeof left === 'string' && typeof right === 'number') {
1737
- const leftNum = parseFloat(left);
1738
- return !isNaN(leftNum) && leftNum === right;
1739
- }
1740
- if (typeof left === 'boolean') {
1741
- return compareEquality(left ? 1 : 0, right);
1742
- }
1743
- if (typeof right === 'boolean') {
1744
- return compareEquality(left, right ? 1 : 0);
1745
- }
1746
- return String(left) === String(right);
1747
- }
1748
- function coerceToComparable(left, right) {
1749
- if (typeof left === 'number' && typeof right === 'number') {
1750
- return [left, right];
1751
- }
1752
- if (typeof left === 'string' && typeof right === 'string') {
1753
- const leftNum = parseFloat(left);
1754
- const rightNum = parseFloat(right);
1755
- if (!isNaN(leftNum) && !isNaN(rightNum)) {
1756
- return [leftNum, rightNum];
1757
- }
1758
- return [left, right];
1759
- }
1760
- const leftNum = toNumberOrNull(left);
1761
- const rightNum = toNumberOrNull(right);
1762
- if (leftNum !== null && rightNum !== null) {
1763
- return [leftNum, rightNum];
1764
- }
1765
- return [String(left), String(right)];
1766
- }
1767
-
1768
- function validResult() {
1769
- return {
1770
- isValid: true,
1771
- errors: [],
1772
- suggestions: [],
1773
- };
1774
- }
1775
- function invalidResult(errors, suggestions = []) {
1776
- return {
1777
- isValid: false,
1778
- errors,
1779
- suggestions,
1780
- };
1781
- }
1782
- function createError(type, message, suggestions = [], severity = 'error') {
1783
- return { type, message, suggestions, severity };
1784
- }
1785
- function validateBinaryInput(input) {
1786
- if (input === null || input === undefined) {
1787
- return invalidResult([createError('missing-argument', 'Input is null or undefined')], ['Provide an object with left and right operands']);
1788
- }
1789
- if (typeof input !== 'object') {
1790
- return invalidResult([createError('type-mismatch', `Expected object, got ${typeof input}`)], ['Provide an object with left and right operands']);
1791
- }
1792
- const obj = input;
1793
- if (!('left' in obj) || !('right' in obj)) {
1794
- const missing = [];
1795
- if (!('left' in obj))
1796
- missing.push('left');
1797
- if (!('right' in obj))
1798
- missing.push('right');
1799
- return invalidResult([
1800
- createError('missing-argument', `Missing ${missing.join(' and ')} operand${missing.length > 1 ? 's' : ''}`),
1801
- ], ['Provide { left: value, right: value }']);
1802
- }
1803
- return validResult();
1804
- }
1805
-
1806
- function trackEvaluation(expression, _context, args, result, startTime, success = true, error) {
1807
- return result;
1808
- }
1809
-
1810
- function isDOMElement(value) {
1811
- return (value !== null &&
1812
- typeof value === 'object' &&
1813
- 'nodeType' in value &&
1814
- value.nodeType === 1);
1815
- }
1816
- const ComparisonInputSchema = v.tuple([v.unknown(), v.unknown()]);
1817
- const PatternMatchingInputSchema = v.tuple([v.unknown(), v.string()]);
1818
- const equalsExpression = {
1819
- name: 'equals',
1820
- category: 'Comparison',
1821
- evaluatesTo: 'Boolean',
1822
- precedence: 10,
1823
- associativity: 'Left',
1824
- operators: ['is', '==', 'equals'],
1825
- async evaluate(context, left, right) {
1826
- const startTime = 0;
1827
- try {
1828
- const result = left == right;
1829
- return trackEvaluation(this, context, [left, right], result, startTime);
1830
- }
1831
- catch (error) {
1832
- throw error;
1833
- }
1834
- },
1835
- validate(args) {
1836
- return validateTwoArgs(args, 'equals');
1837
- },
1838
- inputSchema: ComparisonInputSchema,
1839
- metadata: {
1840
- category: 'Logical',
1841
- complexity: 'simple',
1842
- sideEffects: [],
1843
- dependencies: [],
1844
- returnTypes: ['Boolean'],
1845
- examples: [
1846
- {
1847
- input: 'value is 5',
1848
- description: 'Check if value equals 5 using loose equality',
1849
- expectedOutput: true,
1850
- context: { result: 5 },
1851
- },
1852
- {
1853
- input: '"5" == 5',
1854
- description: 'String "5" equals number 5 with type coercion',
1855
- expectedOutput: true,
1856
- },
1857
- ],
1858
- relatedExpressions: ['strictEquals', 'notEquals'],
1859
- performance: {
1860
- averageTime: 0.001,
1861
- complexity: 'O(1)',
1862
- },
1863
- },
1864
- };
1865
- const strictEqualsExpression = {
1866
- name: 'strictEquals',
1867
- category: 'Comparison',
1868
- evaluatesTo: 'Boolean',
1869
- precedence: 10,
1870
- associativity: 'Left',
1871
- operators: ['==='],
1872
- async evaluate(context, left, right) {
1873
- const result = left === right;
1874
- return result;
1875
- },
1876
- validate(args) {
1877
- return validateTwoArgs(args, 'strictEquals');
1878
- },
1879
- };
1880
- const notEqualsExpression = {
1881
- name: 'notEquals',
1882
- category: 'Comparison',
1883
- evaluatesTo: 'Boolean',
1884
- precedence: 10,
1885
- associativity: 'Left',
1886
- operators: ['!=', 'is not', 'does not equal'],
1887
- async evaluate(context, left, right) {
1888
- const result = left != right;
1889
- return result;
1890
- },
1891
- validate(args) {
1892
- return validateTwoArgs(args, 'notEquals');
1893
- },
1894
- };
1895
- const strictNotEqualsExpression = {
1896
- name: 'strictNotEquals',
1897
- category: 'Comparison',
1898
- evaluatesTo: 'Boolean',
1899
- precedence: 10,
1900
- associativity: 'Left',
1901
- operators: ['!=='],
1902
- async evaluate(context, left, right) {
1903
- const result = left !== right;
1904
- return result;
1905
- },
1906
- validate(args) {
1907
- return validateTwoArgs(args, 'strictNotEquals');
1908
- },
1909
- };
1910
- const lessThanExpression = {
1911
- name: 'lessThan',
1912
- category: 'Comparison',
1913
- evaluatesTo: 'Boolean',
1914
- precedence: 12,
1915
- associativity: 'Left',
1916
- operators: ['<', 'is less than'],
1917
- async evaluate(context, left, right) {
1918
- const result = compareValues(left, right, '<');
1919
- return result;
1920
- },
1921
- validate(args) {
1922
- return validateTwoArgs(args, 'lessThan');
1923
- },
1924
- };
1925
- const lessThanOrEqualExpression = {
1926
- name: 'lessThanOrEqual',
1927
- category: 'Comparison',
1928
- evaluatesTo: 'Boolean',
1929
- precedence: 12,
1930
- associativity: 'Left',
1931
- operators: ['<=', 'is less than or equal to'],
1932
- async evaluate(context, left, right) {
1933
- const result = compareValues(left, right, '<=');
1934
- return result;
1935
- },
1936
- validate(args) {
1937
- return validateTwoArgs(args, 'lessThanOrEqual');
1938
- },
1939
- };
1940
- const greaterThanExpression = {
1941
- name: 'greaterThan',
1942
- category: 'Comparison',
1943
- evaluatesTo: 'Boolean',
1944
- precedence: 12,
1945
- associativity: 'Left',
1946
- operators: ['>', 'is greater than'],
1947
- async evaluate(context, left, right) {
1948
- const result = compareValues(left, right, '>');
1949
- return result;
1950
- },
1951
- validate(args) {
1952
- return validateTwoArgs(args, 'greaterThan');
1953
- },
1954
- };
1955
- const greaterThanOrEqualExpression = {
1956
- name: 'greaterThanOrEqual',
1957
- category: 'Comparison',
1958
- evaluatesTo: 'Boolean',
1959
- precedence: 12,
1960
- associativity: 'Left',
1961
- operators: ['>=', 'is greater than or equal to'],
1962
- async evaluate(context, left, right) {
1963
- const result = compareValues(left, right, '>=');
1964
- return result;
1965
- },
1966
- validate(args) {
1967
- return validateTwoArgs(args, 'greaterThanOrEqual');
1968
- },
1969
- };
1970
- const andExpression = {
1971
- name: 'and',
1972
- category: 'Logical',
1973
- evaluatesTo: 'Boolean',
1974
- precedence: 6,
1975
- associativity: 'Left',
1976
- operators: ['and', '&&'],
1977
- async evaluate(context, left, right) {
1978
- const startTime = 0;
1979
- try {
1980
- const result = left && right;
1981
- return trackEvaluation(this, context, [left, right], result, startTime);
1982
- }
1983
- catch (error) {
1984
- throw error;
1985
- }
1986
- },
1987
- validate(args) {
1988
- return validateTwoArgs(args, 'and');
1989
- },
1990
- inputSchema: ComparisonInputSchema,
1991
- metadata: {
1992
- category: 'Logical',
1993
- complexity: 'simple',
1994
- sideEffects: [],
1995
- dependencies: [],
1996
- returnTypes: ['Boolean'],
1997
- examples: [
1998
- {
1999
- input: 'true and false',
2000
- description: 'Logical AND of boolean values',
2001
- expectedOutput: false,
2002
- },
2003
- {
2004
- input: 'name and age',
2005
- description: 'Both name and age must be truthy',
2006
- expectedOutput: true,
2007
- context: {
2008
- variables: new Map([
2009
- ['name', 'John'],
2010
- ['age', 25],
2011
- ]),
2012
- },
2013
- },
2014
- ],
2015
- relatedExpressions: ['or', 'not'],
2016
- performance: {
2017
- averageTime: 0.001,
2018
- complexity: 'O(1)',
2019
- },
2020
- },
2021
- };
2022
- const orExpression = {
2023
- name: 'or',
2024
- category: 'Logical',
2025
- evaluatesTo: 'Boolean',
2026
- precedence: 5,
2027
- associativity: 'Left',
2028
- operators: ['or', '||'],
2029
- async evaluate(context, left, right) {
2030
- const result = left || right;
2031
- return result;
2032
- },
2033
- validate(args) {
2034
- return validateTwoArgs(args, 'or');
2035
- },
2036
- };
2037
- const notExpression = {
2038
- name: 'not',
2039
- category: 'Logical',
2040
- evaluatesTo: 'Boolean',
2041
- precedence: 15,
2042
- associativity: 'Right',
2043
- operators: ['not', '!'],
2044
- async evaluate(context, operand) {
2045
- const result = !operand;
2046
- return result;
2047
- },
2048
- validate(args) {
2049
- return validateArgCount(args, 1, 'not', 'operand');
2050
- },
2051
- };
2052
- const isEmptyExpression = {
2053
- name: 'isEmpty',
2054
- category: 'Logical',
2055
- evaluatesTo: 'Boolean',
2056
- operators: ['is empty', 'isEmpty'],
2057
- async evaluate(context, value) {
2058
- let result;
2059
- if (value == null)
2060
- result = true;
2061
- else if (isString(value))
2062
- result = value.length === 0;
2063
- else if (Array.isArray(value))
2064
- result = value.length === 0;
2065
- else if (value instanceof NodeList)
2066
- result = value.length === 0;
2067
- else if (value instanceof Node || value instanceof Element)
2068
- result = false;
2069
- else if (isObject(value))
2070
- result = value.length === 0;
2071
- else
2072
- result = false;
2073
- return result;
2074
- },
2075
- validate(args) {
2076
- return validateArgCount(args, 1, 'isEmpty', 'value');
2077
- },
2078
- };
2079
- const noExpression = {
2080
- name: 'no',
2081
- category: 'Logical',
2082
- evaluatesTo: 'Boolean',
2083
- operators: ['no'],
2084
- async evaluate(context, value) {
2085
- let result;
2086
- if (value == null)
2087
- result = true;
2088
- else if (value === false)
2089
- result = true;
2090
- else if (Array.isArray(value))
2091
- result = value.length === 0;
2092
- else if (value instanceof NodeList)
2093
- result = value.length === 0;
2094
- else if (isString(value))
2095
- result = false;
2096
- else
2097
- result = false;
2098
- return result;
2099
- },
2100
- validate(args) {
2101
- return validateArgCount(args, 1, 'no', 'value');
2102
- },
2103
- };
2104
- const isNotEmptyExpression = {
2105
- name: 'isNotEmpty',
2106
- category: 'Logical',
2107
- evaluatesTo: 'Boolean',
2108
- operators: ['is not empty', 'isNotEmpty'],
2109
- async evaluate(context, value) {
2110
- const result = !(await isEmptyExpression.evaluate(context, value));
2111
- return result;
2112
- },
2113
- validate(args) {
2114
- return validateArgCount(args, 1, 'isNotEmpty', 'value');
2115
- },
2116
- };
2117
- const existsExpression = {
2118
- name: 'exists',
2119
- category: 'Logical',
2120
- evaluatesTo: 'Boolean',
2121
- operators: ['exists'],
2122
- async evaluate(context, value) {
2123
- const result = valueExists(value);
2124
- return result;
2125
- },
2126
- validate(args) {
2127
- return validateArgCount(args, 1, 'exists', 'value');
2128
- },
2129
- };
2130
- function valueExists(value) {
2131
- if (value == null)
2132
- return false;
2133
- if (Array.isArray(value))
2134
- return value.length > 0;
2135
- if (typeof NodeList !== 'undefined' && value instanceof NodeList)
2136
- return value.length > 0;
2137
- return true;
2138
- }
2139
- const doesNotExistExpression = {
2140
- name: 'doesNotExist',
2141
- category: 'Logical',
2142
- evaluatesTo: 'Boolean',
2143
- operators: ['does not exist', 'doesNotExist'],
2144
- async evaluate(context, value) {
2145
- const result = !valueExists(value);
2146
- return result;
2147
- },
2148
- validate(args) {
2149
- return validateArgCount(args, 1, 'doesNotExist', 'value');
2150
- },
2151
- };
2152
- const containsExpression = {
2153
- name: 'contains',
2154
- category: 'Logical',
2155
- evaluatesTo: 'Boolean',
2156
- operators: ['contains', 'includes', 'include'],
2157
- async evaluate(context, container, value) {
2158
- let result;
2159
- if (container && value) {
2160
- if (isDOMElement(container) && isDOMElement(value)) {
2161
- result = container.contains(value);
2162
- return result;
2163
- }
2164
- if (isString(container) && container.match(/^[.#][\w-]+$/)) {
2165
- const containerElement = document.querySelector(container);
2166
- if (containerElement && isDOMElement(value)) {
2167
- result = containerElement.contains(value);
2168
- return result;
2169
- }
2170
- if (containerElement && isString(value) && value.match(/^[.#][\w-]+$/)) {
2171
- const valueElement = document.querySelector(value);
2172
- result = valueElement ? containerElement.contains(valueElement) : false;
2173
- return result;
2174
- }
2175
- }
2176
- if (isString(value) && value.match(/^[.#][\w-]+$/) && isDOMElement(container)) {
2177
- const valueElement = document.querySelector(value);
2178
- result = valueElement ? container.contains(valueElement) : false;
2179
- return result;
2180
- }
2181
- }
2182
- if (isString(container) && isString(value)) {
2183
- result = container.includes(value);
2184
- }
2185
- else if (Array.isArray(container) ||
2186
- (typeof NodeList !== 'undefined' && container instanceof NodeList)) {
2187
- const items = Array.from(container);
2188
- result =
2189
- items.includes(value) ||
2190
- (value instanceof Node &&
2191
- items.some(item => item instanceof Node && item.contains(value)));
2192
- }
2193
- else if (isObject(container) && isString(value)) {
2194
- result = value in container;
2195
- }
2196
- else {
2197
- result = false;
2198
- }
2199
- return result;
2200
- },
2201
- validate(args) {
2202
- return validateArgCount(args, 2, 'contains', 'container, value');
2203
- },
2204
- };
2205
- const doesNotContainExpression = {
2206
- name: 'doesNotContain',
2207
- category: 'Logical',
2208
- evaluatesTo: 'Boolean',
2209
- operators: ['does not contain', 'doesNotContain', 'does not include', 'doesNotInclude'],
2210
- async evaluate(context, container, value) {
2211
- const result = !(await containsExpression.evaluate(context, container, value));
2212
- return result;
2213
- },
2214
- validate(args) {
2215
- return validateArgCount(args, 2, 'doesNotContain', 'container, value');
2216
- },
2217
- };
2218
- const startsWithExpression = {
2219
- name: 'startsWith',
2220
- category: 'Logical',
2221
- evaluatesTo: 'Boolean',
2222
- operators: ['starts with', 'startsWith'],
2223
- async evaluate(context, str, prefix) {
2224
- const result = str != null && prefix != null ? String(str).startsWith(String(prefix)) : false;
2225
- return result;
2226
- },
2227
- validate(args) {
2228
- return validateArgCount(args, 2, 'startsWith', 'str, prefix');
2229
- },
2230
- };
2231
- const endsWithExpression = {
2232
- name: 'endsWith',
2233
- category: 'Logical',
2234
- evaluatesTo: 'Boolean',
2235
- operators: ['ends with', 'endsWith'],
2236
- async evaluate(context, str, suffix) {
2237
- const result = str != null && suffix != null ? String(str).endsWith(String(suffix)) : false;
2238
- return result;
2239
- },
2240
- validate(args) {
2241
- return validateArgCount(args, 2, 'endsWith', 'str, suffix');
2242
- },
2243
- };
2244
- const betweenExpression = {
2245
- name: 'between',
2246
- category: 'Logical',
2247
- evaluatesTo: 'Boolean',
2248
- operators: ['is between', 'between'],
2249
- async evaluate(context, value, min, max) {
2250
- let lo = min;
2251
- let hi = max;
2252
- if (lo != null && hi != null && lo > hi) {
2253
- const swap = lo;
2254
- lo = hi;
2255
- hi = swap;
2256
- }
2257
- const result = lo != null &&
2258
- hi != null &&
2259
- value >= lo &&
2260
- value <= hi;
2261
- return result;
2262
- },
2263
- validate(args) {
2264
- return validateArgCount(args, 3, 'between', 'value, min, max');
2265
- },
2266
- };
2267
- const matchesExpression = {
2268
- name: 'matches',
2269
- category: 'Logical',
2270
- evaluatesTo: 'Boolean',
2271
- operators: ['matches'],
2272
- async evaluate(context, element, selector) {
2273
- const startTime = 0;
2274
- try {
2275
- let result;
2276
- if (element instanceof Element && isString(selector)) {
2277
- const selectorStr = selector;
2278
- if (selectorStr.startsWith('.') ||
2279
- selectorStr.startsWith('#') ||
2280
- selectorStr.startsWith(':') ||
2281
- selectorStr.startsWith('[') ||
2282
- /^[a-zA-Z][\w-]*$/.test(selectorStr)) {
2283
- try {
2284
- result = matchesWithCache(element, selectorStr);
2285
- }
2286
- catch (error) {
2287
- result = false;
2288
- }
2289
- }
2290
- else {
2291
- result = false;
2292
- }
2293
- }
2294
- else if (isString(element) && isString(selector)) {
2295
- const elementStr = element;
2296
- const selectorStr = selector;
2297
- try {
2298
- const regex = selectorStr.startsWith('/') && selectorStr.endsWith('/')
2299
- ? new RegExp(selectorStr.slice(1, -1))
2300
- : new RegExp(selectorStr);
2301
- result = regex.test(elementStr);
2302
- }
2303
- catch (error) {
2304
- result = elementStr.includes(selectorStr);
2305
- }
2306
- }
2307
- else {
2308
- result = false;
2309
- }
2310
- return trackEvaluation(this, context, [element, selector], result, startTime);
2311
- }
2312
- catch (error) {
2313
- throw error;
2314
- }
2315
- },
2316
- validate(args) {
2317
- return validateArgCount(args, 2, 'matches', 'element, selector');
2318
- },
2319
- inputSchema: PatternMatchingInputSchema,
2320
- metadata: {
2321
- category: 'Logical',
2322
- complexity: 'medium',
2323
- sideEffects: ['dom-query'],
2324
- dependencies: [],
2325
- returnTypes: ['Boolean'],
2326
- examples: [
2327
- {
2328
- input: 'element matches ".active"',
2329
- description: 'Check if element has active class',
2330
- expectedOutput: true,
2331
- },
2332
- {
2333
- input: 'text matches "/^hello/"',
2334
- description: 'Check if text starts with "hello" using regex',
2335
- expectedOutput: true,
2336
- context: { variables: new Map([['text', 'hello world']]) },
2337
- },
2338
- ],
2339
- relatedExpressions: ['contains', 'startsWith', 'endsWith'],
2340
- performance: {
2341
- averageTime: 0.5,
2342
- complexity: 'O(n)',
2343
- },
2344
- },
2345
- };
2346
- const hasExpression = {
2347
- name: 'has',
2348
- category: 'Logical',
2349
- evaluatesTo: 'Boolean',
2350
- operators: ['has', 'have'],
2351
- async evaluate(context, element, selector) {
2352
- let result = false;
2353
- if (element instanceof Element && isString(selector)) {
2354
- const selectorStr = selector;
2355
- if (selectorStr.startsWith('.')) {
2356
- result = element.classList.contains(selectorStr.slice(1));
2357
- }
2358
- else if (selectorStr.startsWith('[') && selectorStr.endsWith(']')) {
2359
- result = element.hasAttribute(selectorStr.slice(1, -1));
2360
- }
2361
- }
2362
- return result;
2363
- },
2364
- validate(args) {
2365
- return validateArgCount(args, 2, 'has', 'element, selector');
2366
- },
2367
- };
2368
- const doesNotHaveExpression = {
2369
- name: 'doesNotHave',
2370
- category: 'Logical',
2371
- evaluatesTo: 'Boolean',
2372
- operators: ['does not have'],
2373
- async evaluate(context, element, selector) {
2374
- const result = !(await hasExpression.evaluate(context, element, selector));
2375
- return result;
2376
- },
2377
- validate(args) {
2378
- return validateArgCount(args, 2, 'doesNotHave', 'element, selector');
2379
- },
2380
- };
2381
- const logicalExpressions = {
2382
- equals: equalsExpression,
2383
- strictEquals: strictEqualsExpression,
2384
- notEquals: notEqualsExpression,
2385
- strictNotEquals: strictNotEqualsExpression,
2386
- lessThan: lessThanExpression,
2387
- lessThanOrEqual: lessThanOrEqualExpression,
2388
- greaterThan: greaterThanExpression,
2389
- greaterThanOrEqual: greaterThanOrEqualExpression,
2390
- and: andExpression,
2391
- or: orExpression,
2392
- not: notExpression,
2393
- no: noExpression,
2394
- isEmpty: isEmptyExpression,
2395
- isNotEmpty: isNotEmptyExpression,
2396
- exists: existsExpression,
2397
- doesNotExist: doesNotExistExpression,
2398
- contains: containsExpression,
2399
- doesNotContain: doesNotContainExpression,
2400
- startsWith: startsWithExpression,
2401
- endsWith: endsWithExpression,
2402
- between: betweenExpression,
2403
- matches: matchesExpression,
2404
- has: hasExpression,
2405
- doesNotHave: doesNotHaveExpression,
2406
- };
2407
-
2408
- class BaseExpressionImpl {
2409
- trackPerformance(context, input, result, startTime) {
2410
- }
2411
- trackSimple(context, startTime, success, output = success ? 'success' : 'error') {
2412
- }
2413
- toBoolean(value) {
2414
- if (value === false ||
2415
- value === 0 ||
2416
- value === 0n ||
2417
- value === '' ||
2418
- value === null ||
2419
- value === undefined) {
2420
- return false;
2421
- }
2422
- if (isNumber(value) && isNaN(value)) {
2423
- return false;
2424
- }
2425
- return true;
2426
- }
2427
- success(value, type) {
2428
- return {
2429
- success: true,
2430
- value,
2431
- type,
2432
- };
2433
- }
2434
- failure(name, type, message, code, suggestions = []) {
2435
- return {
2436
- success: false,
2437
- error: {
2438
- name,
2439
- type,
2440
- message,
2441
- code,
2442
- suggestions,
2443
- },
2444
- };
2445
- }
2446
- validationSuccess() {
2447
- return {
2448
- isValid: true,
2449
- errors: [],
2450
- suggestions: [],
2451
- };
2452
- }
2453
- validationFailure(type, message, suggestions = []) {
2454
- return {
2455
- isValid: false,
2456
- errors: [{ type, message, suggestions }],
2457
- suggestions,
2458
- };
2459
- }
2460
- isElement(value) {
2461
- return (value !== null &&
2462
- typeof value === 'object' &&
2463
- 'nodeType' in value &&
2464
- value.nodeType === 1 &&
2465
- 'tagName' in value &&
2466
- typeof value.tagName === 'string');
2467
- }
2468
- inferType(value) {
2469
- if (value === null)
2470
- return 'null';
2471
- if (value === undefined)
2472
- return 'undefined';
2473
- if (this.isElement(value))
2474
- return 'element';
2475
- if (Array.isArray(value))
2476
- return 'array';
2477
- if (isObject(value))
2478
- return 'object';
2479
- return typeof value;
2480
- }
2481
- inferEvaluationType(value) {
2482
- if (value === undefined)
2483
- return 'Undefined';
2484
- if (value === null)
2485
- return 'Null';
2486
- if (isString(value))
2487
- return 'String';
2488
- if (isNumber(value))
2489
- return 'Number';
2490
- if (isBoolean(value))
2491
- return 'Boolean';
2492
- if (Array.isArray(value))
2493
- return 'Array';
2494
- if (this.isElement(value))
2495
- return 'Element';
2496
- return 'Object';
2497
- }
2498
- normalizeCollection(collection) {
2499
- if (Array.isArray(collection))
2500
- return collection;
2501
- if (collection instanceof NodeList)
2502
- return Array.from(collection);
2503
- if (isString(collection))
2504
- return collection.split('');
2505
- if (collection == null)
2506
- return [];
2507
- if (isObject(collection) && Symbol.iterator in collection) {
2508
- return Array.from(collection);
2509
- }
2510
- return [];
2511
- }
2512
- toNumber(value) {
2513
- if (isNumber(value) && Number.isFinite(value))
2514
- return value;
2515
- if (isString(value)) {
2516
- const num = Number(value);
2517
- return Number.isFinite(num) ? num : null;
2518
- }
2519
- if (isBoolean(value))
2520
- return value ? 1 : 0;
2521
- return null;
2522
- }
2523
- }
2524
-
2525
- const LOCAL_READ_HOOKS = new Set();
2526
- function report(kind, err) {
2527
- if (typeof console !== 'undefined') {
2528
- console.error(`[hyperfixi] ${kind} threw:`, err);
2529
- }
2530
- }
2531
- function notifyLocalRead(name, context) {
2532
- if (LOCAL_READ_HOOKS.size === 0)
2533
- return;
2534
- for (const hook of LOCAL_READ_HOOKS) {
2535
- try {
2536
- hook(name, context);
2537
- }
2538
- catch (err) {
2539
- report('localReadHook', err);
2540
- }
2541
- }
2542
- }
2543
-
2544
- const StringLiteralInputSchema = v
2545
- .object({
2546
- value: v.string().describe('String literal value'),
2547
- })
2548
- .strict();
2549
- const NumberLiteralInputSchema = v
2550
- .object({
2551
- value: v.number().describe('Number literal value'),
2552
- })
2553
- .strict();
2554
- const BooleanLiteralInputSchema = v
2555
- .object({
2556
- value: v.boolean().describe('Boolean literal value'),
2557
- })
2558
- .strict();
2559
- const BinaryOperationInputSchema = v
2560
- .object({
2561
- left: v.unknown().describe('Left operand'),
2562
- right: v.unknown().describe('Right operand'),
2563
- })
2564
- .strict();
2565
- class StringLiteralExpression extends BaseExpressionImpl {
2566
- constructor() {
2567
- super(...arguments);
2568
- this.name = 'stringLiteral';
2569
- this.category = 'Special';
2570
- this.syntax = '"string" or \'string\'';
2571
- this.description = 'String literals with template interpolation support';
2572
- this.outputType = 'String';
2573
- this.inputSchema = StringLiteralInputSchema;
2574
- this.metadata = {
2575
- category: 'Special',
2576
- complexity: 'simple',
2577
- };
2578
- }
2579
- async evaluate(context, input) {
2580
- const startTime = Date.now();
2581
- try {
2582
- const validation = this.validate(input);
2583
- if (!validation.isValid) {
2584
- const result = this.failure('ValidationError', 'validation-error', validation.errors.map(e => e.message).join(', '), 'VALIDATION_FAILED', validation.suggestions);
2585
- this.trackSimple(context, startTime, false);
2586
- return result;
2587
- }
2588
- let resultValue = input.value;
2589
- if (resultValue.includes('${') || resultValue.includes('$')) {
2590
- resultValue = this.interpolateString(resultValue, context);
2591
- }
2592
- const result = this.success(resultValue, 'string');
2593
- this.trackSimple(context, startTime, true, resultValue);
2594
- return result;
2595
- }
2596
- catch (error) {
2597
- this.trackSimple(context, startTime, false);
2598
- return this.failure('StringEvaluationError', 'runtime-error', `String literal evaluation failed: ${error instanceof Error ? error.message : String(error)}`, 'STRING_EVALUATION_FAILED');
2599
- }
2600
- }
2601
- validate(input) {
2602
- try {
2603
- const parsed = this.inputSchema.safeParse(input);
2604
- if (!parsed.success) {
2605
- return this.validationFailure('type-mismatch', parsed.error?.errors.map(err => err.message).join(', ') || 'Invalid string literal input', ['Provide a value parameter', 'Ensure value is a string']);
2606
- }
2607
- return this.validationSuccess();
2608
- }
2609
- catch (_error) {
2610
- return this.validationFailure('runtime-error', 'Validation failed with exception', [
2611
- 'Check input structure and types',
2612
- ]);
2613
- }
2614
- }
2615
- interpolateString(template, context) {
2616
- let result = template.replace(/\$\{([^}]+)\}/g, (_match, expression) => {
2617
- try {
2618
- const value = this.resolveExpression(expression.trim(), context);
2619
- return value !== undefined ? String(value) : '';
2620
- }
2621
- catch (_error) {
2622
- return '';
2623
- }
2624
- });
2625
- result = result.replace(/\$([a-zA-Z_$][a-zA-Z0-9_.$]*)/g, (_match, varName) => {
2626
- try {
2627
- const value = this.resolveVariable(varName, context);
2628
- return value !== undefined ? String(value) : '';
2629
- }
2630
- catch (_error) {
2631
- return '';
2632
- }
2633
- });
2634
- return result;
2635
- }
2636
- resolveExpression(expression, context) {
2637
- if (expression.includes('.')) {
2638
- const parts = expression.split('.');
2639
- let value = this.resolveVariable(parts[0], context);
2640
- for (let i = 1; i < parts.length && value != null; i++) {
2641
- value = value[parts[i]];
2642
- }
2643
- return value;
2644
- }
2645
- return this.resolveVariable(expression, context);
2646
- }
2647
- resolveVariable(varName, context) {
2648
- if (varName === 'me' && context.me)
2649
- return context.me;
2650
- if (varName === 'you' && context.you)
2651
- return context.you;
2652
- if (varName === 'it' && context.it)
2653
- return context.it;
2654
- if (varName === 'result' && context.result)
2655
- return context.result;
2656
- if (context.locals?.has(varName)) {
2657
- notifyLocalRead(varName, context);
2658
- return context.locals.get(varName);
2659
- }
2660
- if (context.globals?.has(varName)) {
2661
- return context.globals.get(varName);
2662
- }
2663
- return undefined;
2664
- }
2665
- }
2666
- class NumberLiteralExpression extends BaseExpressionImpl {
2667
- constructor() {
2668
- super(...arguments);
2669
- this.name = 'numberLiteral';
2670
- this.category = 'Special';
2671
- this.syntax = '123 or 3.14';
2672
- this.description = 'Numeric literal with validation';
2673
- this.inputSchema = NumberLiteralInputSchema;
2674
- this.outputType = 'Number';
2675
- this.metadata = {
2676
- category: 'Special',
2677
- complexity: 'simple',
2678
- };
2679
- }
2680
- async evaluate(context, input) {
2681
- const startTime = Date.now();
2682
- try {
2683
- const validation = this.validate(input);
2684
- if (!validation.isValid) {
2685
- this.trackSimple(context, startTime, false);
2686
- return this.failure('ValidationError', 'validation-error', validation.errors.map(e => e.message).join(', '), 'VALIDATION_FAILED', validation.suggestions);
2687
- }
2688
- if (!Number.isFinite(input.value)) {
2689
- this.trackSimple(context, startTime, false);
2690
- return this.failure('NumberValidationError', 'invalid-argument', 'Number literal must be finite', 'NUMBER_NOT_FINITE');
2691
- }
2692
- this.trackSimple(context, startTime, true, input.value);
2693
- return this.success(input.value, 'number');
2694
- }
2695
- catch (error) {
2696
- this.trackSimple(context, startTime, false);
2697
- return this.failure('NumberEvaluationError', 'runtime-error', `Number literal evaluation failed: ${error instanceof Error ? error.message : String(error)}`, 'NUMBER_EVALUATION_FAILED');
2698
- }
2699
- }
2700
- validate(input) {
2701
- try {
2702
- const parsed = this.inputSchema.safeParse(input);
2703
- if (!parsed.success) {
2704
- return this.validationFailure('type-mismatch', parsed.error?.errors.map(err => err.message).join(', ') || 'Invalid number literal input', ['Provide a value parameter', 'Ensure value is a number']);
2705
- }
2706
- if (!Number.isFinite(parsed.data.value)) {
2707
- return this.validationFailure('invalid-argument', 'Number literal value must be finite', [
2708
- 'Use finite numbers only',
2709
- 'Avoid Infinity and NaN values',
2710
- ]);
2711
- }
2712
- return this.validationSuccess();
2713
- }
2714
- catch (_error) {
2715
- return this.validationFailure('runtime-error', 'Validation failed with exception', [
2716
- 'Check input structure and types',
2717
- ]);
2718
- }
2719
- }
2720
- }
2721
- class BooleanLiteralExpression extends BaseExpressionImpl {
2722
- constructor() {
2723
- super(...arguments);
2724
- this.name = 'booleanLiteral';
2725
- this.category = 'Special';
2726
- this.syntax = 'true or false';
2727
- this.description = 'Boolean literal values';
2728
- this.inputSchema = BooleanLiteralInputSchema;
2729
- this.outputType = 'Boolean';
2730
- this.metadata = {
2731
- category: 'Special',
2732
- complexity: 'simple',
2733
- };
2734
- }
2735
- async evaluate(context, input) {
2736
- const startTime = Date.now();
2737
- try {
2738
- const validation = this.validate(input);
2739
- if (!validation.isValid) {
2740
- this.trackSimple(context, startTime, false);
2741
- return this.failure('ValidationError', 'validation-error', validation.errors.map(e => e.message).join(', '), 'VALIDATION_FAILED', validation.suggestions);
2742
- }
2743
- this.trackSimple(context, startTime, true, input.value);
2744
- return this.success(input.value, 'boolean');
2745
- }
2746
- catch (error) {
2747
- this.trackSimple(context, startTime, false);
2748
- return this.failure('BooleanEvaluationError', 'runtime-error', `Boolean literal evaluation failed: ${error instanceof Error ? error.message : String(error)}`, 'BOOLEAN_EVALUATION_FAILED');
2749
- }
2750
- }
2751
- validate(input) {
2752
- try {
2753
- const parsed = this.inputSchema.safeParse(input);
2754
- if (!parsed.success) {
2755
- return this.validationFailure('type-mismatch', parsed.error?.errors.map(err => err.message).join(', ') ||
2756
- 'Invalid boolean literal input', ['Provide a value parameter', 'Ensure value is a boolean']);
2757
- }
2758
- return this.validationSuccess();
2759
- }
2760
- catch (_error) {
2761
- return this.validationFailure('runtime-error', 'Validation failed with exception', [
2762
- 'Check input structure and types',
2763
- ]);
2764
- }
2765
- }
2766
- }
2767
- class StringConcatenationExpression extends BaseExpressionImpl {
2768
- constructor() {
2769
- super(...arguments);
2770
- this.name = 'stringConcatenation';
2771
- this.category = 'Special';
2772
- this.syntax = 'left + right (string concatenation)';
2773
- this.description = 'Concatenation of two values into a string';
2774
- this.inputSchema = BinaryOperationInputSchema;
2775
- this.outputType = 'String';
2776
- this.metadata = {
2777
- category: 'Special',
2778
- complexity: 'simple',
2779
- };
2780
- }
2781
- async evaluate(context, input) {
2782
- const startTime = Date.now();
2783
- try {
2784
- const validation = this.validate(input);
2785
- if (!validation.isValid) {
2786
- this.trackSimple(context, startTime, false);
2787
- return this.failure('ValidationError', 'validation-error', validation.errors[0]?.message || 'Invalid input', 'STRING_CONCATENATION_VALIDATION_FAILED', validation.suggestions);
2788
- }
2789
- const leftStr = this.convertToString(input.left);
2790
- const rightStr = this.convertToString(input.right);
2791
- const result = leftStr + rightStr;
2792
- this.trackSimple(context, startTime, true, result);
2793
- return this.success(result, 'string');
2794
- }
2795
- catch (error) {
2796
- this.trackSimple(context, startTime, false);
2797
- return this.failure('StringConcatenationError', 'runtime-error', error instanceof Error ? error.message : 'String concatenation failed', 'STRING_CONCATENATION_ERROR', ['Check that operands can be converted to strings']);
2798
- }
2799
- }
2800
- validate(input) {
2801
- const parsed = BinaryOperationInputSchema.safeParse(input);
2802
- if (!parsed.success) {
2803
- return this.validationFailure('type-mismatch', parsed.error?.errors.map(err => err.message).join(', ') ||
2804
- 'Invalid string concatenation input', ['Provide left and right operands for concatenation']);
2805
- }
2806
- return this.validationSuccess();
2807
- }
2808
- convertToString(value) {
2809
- if (value === null)
2810
- return 'null';
2811
- if (value === undefined)
2812
- return 'undefined';
2813
- if (isString(value))
2814
- return value;
2815
- if (isNumber(value))
2816
- return value.toString();
2817
- if (isBoolean(value))
2818
- return value.toString();
2819
- if (value instanceof Date)
2820
- return value.toString();
2821
- try {
2822
- return String(value);
2823
- }
2824
- catch {
2825
- return '[object Object]';
2826
- }
2827
- }
2828
- }
2829
- function createStringLiteralExpression() {
2830
- return new StringLiteralExpression();
2831
- }
2832
- function createNumberLiteralExpression() {
2833
- return new NumberLiteralExpression();
2834
- }
2835
- function createBooleanLiteralExpression() {
2836
- return new BooleanLiteralExpression();
2837
- }
2838
- function createStringConcatenationExpression() {
2839
- return new StringConcatenationExpression();
2840
- }
2841
- const specialExpressions = {
2842
- stringLiteral: createStringLiteralExpression(),
2843
- numberLiteral: createNumberLiteralExpression(),
2844
- booleanLiteral: createBooleanLiteralExpression(),
2845
- stringConcatenation: createStringConcatenationExpression(),
2846
- };
2847
-
2848
- class AdditionExpression {
2849
- constructor() {
2850
- this.name = 'addition';
2851
- this.category = 'Special';
2852
- this.syntax = 'left + right';
2853
- this.outputType = 'number';
2854
- this.metadata = { category: 'Special', complexity: 'simple' };
2855
- }
2856
- async evaluate(_context, input) {
2857
- const validation = this.validate(input);
2858
- if (!validation.isValid) {
2859
- return { success: false, errors: validation.errors, suggestions: validation.suggestions };
2860
- }
2861
- try {
2862
- const { left, right } = input;
2863
- const leftNum = toNumber(left, 'left operand');
2864
- const rightNum = toNumber(right, 'right operand');
2865
- const result = ensureFinite(leftNum + rightNum, 'addition');
2866
- return { success: true, value: result, type: 'number' };
2867
- }
2868
- catch (error) {
2869
- return {
2870
- success: false,
2871
- errors: [
2872
- createError('runtime-error', `Addition failed: ${error instanceof Error ? error.message : String(error)}`),
2873
- ],
2874
- suggestions: ['Ensure both operands are numeric'],
2875
- };
2876
- }
2877
- }
2878
- validate(input) {
2879
- const result = validateBinaryInput(input);
2880
- if (!result.isValid)
2881
- return result;
2882
- const { left, right } = input;
2883
- if (!canBeNumeric(left)) {
2884
- return {
2885
- isValid: false,
2886
- errors: [
2887
- createError('type-mismatch', `Left operand cannot be converted to number: ${String(left)}`),
2888
- ],
2889
- suggestions: ['Provide a numeric value for left operand'],
2890
- };
2891
- }
2892
- if (!canBeNumeric(right)) {
2893
- return {
2894
- isValid: false,
2895
- errors: [
2896
- createError('type-mismatch', `Right operand cannot be converted to number: ${String(right)}`),
2897
- ],
2898
- suggestions: ['Provide a numeric value for right operand'],
2899
- };
2900
- }
2901
- return { isValid: true, errors: [], suggestions: [] };
2902
- }
2903
- }
2904
- class SubtractionExpression {
2905
- constructor() {
2906
- this.name = 'subtraction';
2907
- this.category = 'Special';
2908
- this.syntax = 'left - right';
2909
- this.outputType = 'number';
2910
- this.metadata = { category: 'Special', complexity: 'simple' };
2911
- }
2912
- async evaluate(_context, input) {
2913
- const validation = this.validate(input);
2914
- if (!validation.isValid) {
2915
- return { success: false, errors: validation.errors, suggestions: validation.suggestions };
2916
- }
2917
- try {
2918
- const { left, right } = input;
2919
- const leftNum = toNumber(left, 'left operand');
2920
- const rightNum = toNumber(right, 'right operand');
2921
- const result = ensureFinite(leftNum - rightNum, 'subtraction');
2922
- return { success: true, value: result, type: 'number' };
2923
- }
2924
- catch (error) {
2925
- return {
2926
- success: false,
2927
- errors: [
2928
- createError('runtime-error', `Subtraction failed: ${error instanceof Error ? error.message : String(error)}`),
2929
- ],
2930
- suggestions: ['Ensure both operands are numeric'],
2931
- };
2932
- }
2933
- }
2934
- validate(input) {
2935
- const addExpr = new AdditionExpression();
2936
- return addExpr.validate(input);
2937
- }
2938
- }
2939
- class MultiplicationExpression {
2940
- constructor() {
2941
- this.name = 'multiplication';
2942
- this.category = 'Special';
2943
- this.syntax = 'left * right';
2944
- this.outputType = 'number';
2945
- this.metadata = { category: 'Special', complexity: 'simple' };
2946
- }
2947
- async evaluate(_context, input) {
2948
- const validation = this.validate(input);
2949
- if (!validation.isValid) {
2950
- return { success: false, errors: validation.errors, suggestions: validation.suggestions };
2951
- }
2952
- try {
2953
- const { left, right } = input;
2954
- const leftNum = toNumber(left, 'left operand');
2955
- const rightNum = toNumber(right, 'right operand');
2956
- const result = ensureFinite(leftNum * rightNum, 'multiplication');
2957
- return { success: true, value: result, type: 'number' };
2958
- }
2959
- catch (error) {
2960
- return {
2961
- success: false,
2962
- errors: [
2963
- createError('runtime-error', `Multiplication failed: ${error instanceof Error ? error.message : String(error)}`),
2964
- ],
2965
- suggestions: ['Ensure both operands are numeric'],
2966
- };
2967
- }
2968
- }
2969
- validate(input) {
2970
- const addExpr = new AdditionExpression();
2971
- return addExpr.validate(input);
2972
- }
2973
- }
2974
- class DivisionExpression {
2975
- constructor() {
2976
- this.name = 'division';
2977
- this.category = 'Special';
2978
- this.syntax = 'left / right';
2979
- this.outputType = 'number';
2980
- this.metadata = { category: 'Special', complexity: 'simple' };
2981
- }
2982
- async evaluate(_context, input) {
2983
- const validation = this.validate(input);
2984
- if (!validation.isValid) {
2985
- return { success: false, errors: validation.errors, suggestions: validation.suggestions };
2986
- }
2987
- try {
2988
- const { left, right } = input;
2989
- const leftNum = toNumber(left, 'left operand');
2990
- const rightNum = toNumber(right, 'right operand');
2991
- const result = safeDivide(leftNum, rightNum, true);
2992
- return { success: true, value: result, type: 'number' };
2993
- }
2994
- catch (error) {
2995
- return {
2996
- success: false,
2997
- errors: [
2998
- createError('runtime-error', `Division failed: ${error instanceof Error ? error.message : String(error)}`),
2999
- ],
3000
- suggestions: ['Ensure both operands are numeric'],
3001
- };
3002
- }
3003
- }
3004
- validate(input) {
3005
- const addExpr = new AdditionExpression();
3006
- return addExpr.validate(input);
3007
- }
3008
- }
3009
- class ModuloExpression {
3010
- constructor() {
3011
- this.name = 'modulo';
3012
- this.category = 'Special';
3013
- this.syntax = 'left mod right';
3014
- this.outputType = 'number';
3015
- this.metadata = { category: 'Special', complexity: 'simple' };
3016
- }
3017
- async evaluate(_context, input) {
3018
- const validation = this.validate(input);
3019
- if (!validation.isValid) {
3020
- return { success: false, errors: validation.errors, suggestions: validation.suggestions };
3021
- }
3022
- try {
3023
- const { left, right } = input;
3024
- const leftNum = toNumber(left, 'left operand');
3025
- const rightNum = toNumber(right, 'right operand');
3026
- const result = safeModulo(leftNum, rightNum);
3027
- return { success: true, value: result, type: 'number' };
3028
- }
3029
- catch (error) {
3030
- return {
3031
- success: false,
3032
- errors: [
3033
- createError('runtime-error', `Modulo failed: ${error instanceof Error ? error.message : String(error)}`),
3034
- ],
3035
- suggestions: ['Ensure both operands are numeric and divisor is not zero'],
3036
- };
3037
- }
3038
- }
3039
- validate(input) {
3040
- const addExpr = new AdditionExpression();
3041
- return addExpr.validate(input);
3042
- }
3043
- }
3044
- class PowerExpression {
3045
- constructor() {
3046
- this.name = 'power';
3047
- this.category = 'Special';
3048
- this.syntax = 'left ** right';
3049
- this.outputType = 'number';
3050
- this.metadata = { category: 'Special', complexity: 'simple' };
3051
- }
3052
- async evaluate(_context, input) {
3053
- const validation = this.validate(input);
3054
- if (!validation.isValid) {
3055
- return { success: false, errors: validation.errors, suggestions: validation.suggestions };
3056
- }
3057
- try {
3058
- const { left, right } = input;
3059
- const leftNum = toNumber(left, 'left operand');
3060
- const rightNum = toNumber(right, 'right operand');
3061
- const result = ensureFinite(Math.pow(leftNum, rightNum), 'power');
3062
- return { success: true, value: result, type: 'number' };
3063
- }
3064
- catch (error) {
3065
- return {
3066
- success: false,
3067
- errors: [
3068
- createError('runtime-error', `Power failed: ${error instanceof Error ? error.message : String(error)}`),
3069
- ],
3070
- suggestions: ['Ensure both operands are numeric'],
3071
- };
3072
- }
3073
- }
3074
- validate(input) {
3075
- const addExpr = new AdditionExpression();
3076
- return addExpr.validate(input);
3077
- }
3078
- }
3079
- function createAdditionExpression() {
3080
- return new AdditionExpression();
3081
- }
3082
- function createSubtractionExpression() {
3083
- return new SubtractionExpression();
3084
- }
3085
- function createMultiplicationExpression() {
3086
- return new MultiplicationExpression();
3087
- }
3088
- function createDivisionExpression() {
3089
- return new DivisionExpression();
3090
- }
3091
- function createModuloExpression() {
3092
- return new ModuloExpression();
3093
- }
3094
- function createPowerExpression() {
3095
- return new PowerExpression();
3096
- }
3097
- const mathematicalExpressions = {
3098
- addition: createAdditionExpression(),
3099
- subtraction: createSubtractionExpression(),
3100
- multiplication: createMultiplicationExpression(),
3101
- division: createDivisionExpression(),
3102
- modulo: createModuloExpression(),
3103
- power: createPowerExpression(),
3104
- };
3105
-
3106
- function createCoreRegistry() {
3107
- return createExpressionRegistry(referencesExpressions, logicalExpressions, specialExpressions, mathematicalExpressions);
3108
- }
3109
-
3110
- const conversionConfig = {
3111
- conversions: { dynamicResolvers: [] },
3112
- };
3113
- const defaultConversions = {
3114
- Array: (value) => {
3115
- if (Array.isArray(value))
3116
- return value;
3117
- if (value instanceof NodeList)
3118
- return Array.from(value);
3119
- if (value == null)
3120
- return [];
3121
- return [value];
3122
- },
3123
- String: (value) => {
3124
- if (value == null)
3125
- return '';
3126
- if (isString(value))
3127
- return value;
3128
- if (isObject(value))
3129
- return JSON.stringify(value);
3130
- return String(value);
3131
- },
3132
- Boolean: (value) => {
3133
- if (isBoolean(value))
3134
- return value;
3135
- if (value == null)
3136
- return false;
3137
- if (isString(value)) {
3138
- const lowerValue = value.toLowerCase().trim();
3139
- if (lowerValue === 'false' || lowerValue === '0' || lowerValue === '')
3140
- return false;
3141
- return true;
3142
- }
3143
- if (isNumber(value)) {
3144
- return value !== 0 && !isNaN(value);
3145
- }
3146
- return Boolean(value);
3147
- },
3148
- Number: (value) => {
3149
- if (isNumber(value))
3150
- return value;
3151
- if (value == null)
3152
- return 0;
3153
- const num = Number(value);
3154
- return isNaN(num) ? 0 : num;
3155
- },
3156
- Math: (value) => {
3157
- if (isNumber(value))
3158
- return value;
3159
- if (value == null)
3160
- return 0;
3161
- const expression = String(value).trim();
3162
- if (!expression)
3163
- return 0;
3164
- try {
3165
- return evaluateMathExpression(expression);
3166
- }
3167
- catch (error) {
3168
- console.warn('Math conversion failed:', error);
3169
- return 0;
3170
- }
3171
- },
3172
- Int: (value) => {
3173
- const num = defaultConversions.Number(value);
3174
- return Math.trunc(num);
3175
- },
3176
- Float: (value) => {
3177
- const num = defaultConversions.Number(value);
3178
- return parseFloat(num.toString());
3179
- },
3180
- Date: (value) => {
3181
- if (value instanceof Date)
3182
- return value;
3183
- if (value == null)
3184
- return new Date(NaN);
3185
- if (isString(value) && /^\d{4}-\d{2}-\d{2}$/.test(value)) {
3186
- const [year, month, day] = value.split('-').map(Number);
3187
- return new Date(year, month - 1, day);
3188
- }
3189
- const date = new Date(value);
3190
- return date;
3191
- },
3192
- JSON: (value) => {
3193
- if (!isString(value))
3194
- return value;
3195
- try {
3196
- return JSON.parse(value);
3197
- }
3198
- catch {
3199
- return value;
3200
- }
3201
- },
3202
- JSONString: (value) => {
3203
- try {
3204
- return JSON.stringify(value);
3205
- }
3206
- catch {
3207
- return '{}';
3208
- }
3209
- },
3210
- Object: (value) => {
3211
- if (isObject(value))
3212
- return value;
3213
- if (isString(value)) {
3214
- try {
3215
- return JSON.parse(value);
3216
- }
3217
- catch (error) {
3218
- return {};
3219
- }
3220
- }
3221
- return {};
3222
- },
3223
- Fragment: (value) => {
3224
- const frag = document.createDocumentFragment();
3225
- const items = Array.isArray(value) || value instanceof NodeList
3226
- ? Array.from(value)
3227
- : [value];
3228
- for (const item of items) {
3229
- if (item instanceof Node) {
3230
- frag.append(item);
3231
- }
3232
- else {
3233
- const template = document.createElement('template');
3234
- template.innerHTML = item == null ? '' : String(item);
3235
- frag.append(template.content);
3236
- }
3237
- }
3238
- return frag;
3239
- },
3240
- HTML: (value) => {
3241
- if (isString(value))
3242
- return value;
3243
- if (value instanceof NodeList) {
3244
- return Array.from(value)
3245
- .map(node => (node instanceof Element ? node.outerHTML : node.textContent || ''))
3246
- .join('');
3247
- }
3248
- if (Array.isArray(value)) {
3249
- return value
3250
- .map(item => (item instanceof Element ? item.outerHTML : defaultConversions.String(item)))
3251
- .join('');
3252
- }
3253
- if (value instanceof Element) {
3254
- return value.outerHTML;
3255
- }
3256
- return defaultConversions.String(value);
3257
- },
3258
- Values: (value, _context) => {
3259
- if (value instanceof HTMLFormElement) {
3260
- return getFormValuesProcessed(value);
3261
- }
3262
- if (value instanceof HTMLElement) {
3263
- const inputs = value.querySelectorAll('input, select, textarea');
3264
- const values = {};
3265
- inputs.forEach((input) => {
3266
- const htmlInput = input;
3267
- if (htmlInput.name) {
3268
- values[htmlInput.name] = getInputValue(htmlInput);
3269
- }
3270
- });
3271
- return values;
3272
- }
3273
- return {};
3274
- },
3275
- FormEncoded: (value, context) => {
3276
- const values = value instanceof HTMLElement ? defaultConversions.Values(value, context) : value;
3277
- if (!isObject(values))
3278
- return '';
3279
- const params = new URLSearchParams();
3280
- for (const [k, v] of Object.entries(values)) {
3281
- if (v === undefined || v === null)
3282
- continue;
3283
- if (Array.isArray(v)) {
3284
- for (const item of v)
3285
- params.append(k, String(item));
3286
- }
3287
- else {
3288
- params.append(k, String(v));
3289
- }
3290
- }
3291
- return params.toString();
3292
- },
3293
- Set: (value) => new Set(value),
3294
- Map: (value) => new Map(Object.entries((value ?? {}))),
3295
- Keys: (value) => {
3296
- if (value instanceof Map)
3297
- return Array.from(value.keys());
3298
- return Object.keys((value ?? {}));
3299
- },
3300
- Entries: (value) => {
3301
- if (value instanceof Map)
3302
- return Array.from(value.entries());
3303
- return Object.entries((value ?? {}));
3304
- },
3305
- Reversed: (value) => Array.from(value).reverse(),
3306
- Unique: (value) => [...new Set(value)],
3307
- Flat: (value) => Array.from(value).flat(),
3308
- 'Values:Form': (value, context) => {
3309
- const values = defaultConversions.Values(value, context);
3310
- return defaultConversions.FormEncoded(values, context);
3311
- },
3312
- 'Values:JSON': (value, context) => {
3313
- const values = defaultConversions.Values(value, context);
3314
- return JSON.stringify(values);
3315
- },
3316
- };
3317
- function evaluateMathExpression(expression) {
3318
- expression = expression.replace(/\s/g, '');
3319
- if (!/^[0-9+\-*/().]+$/.test(expression)) {
3320
- throw new Error('Invalid characters in math expression');
3321
- }
3322
- try {
3323
- const result = new Function(`"use strict"; return (${expression})`)();
3324
- if (!isNumber(result) || !isFinite(result)) {
3325
- throw new Error('Expression did not evaluate to a finite number');
3326
- }
3327
- return result;
3328
- }
3329
- catch (error) {
3330
- throw new Error(`Math expression evaluation failed: ${error instanceof Error ? error.message : String(error)}`);
3331
- }
3332
- }
3333
- function getFormValuesProcessed(form) {
3334
- const values = {};
3335
- const elements = form.querySelectorAll('input, select, textarea');
3336
- elements.forEach(element => {
3337
- const input = element;
3338
- if (input.name) {
3339
- const value = getInputValue(input);
3340
- if (value !== undefined) {
3341
- if (values[input.name] !== undefined) {
3342
- if (!Array.isArray(values[input.name])) {
3343
- values[input.name] = [values[input.name]];
3344
- }
3345
- values[input.name].push(value);
3346
- }
3347
- else {
3348
- values[input.name] = value;
3349
- }
3350
- }
3351
- }
3352
- });
3353
- return values;
3354
- }
3355
- function getInputValue(input) {
3356
- if (input instanceof HTMLInputElement) {
3357
- switch (input.type) {
3358
- case 'checkbox':
3359
- return input.checked;
3360
- case 'radio':
3361
- return input.checked ? input.value : undefined;
3362
- case 'number':
3363
- case 'range':
3364
- return input.valueAsNumber;
3365
- case 'date':
3366
- case 'datetime-local':
3367
- return input.valueAsDate;
3368
- case 'file':
3369
- return input.files;
3370
- default:
3371
- return input.value;
3372
- }
3373
- }
3374
- if (input instanceof HTMLSelectElement) {
3375
- if (input.multiple) {
3376
- return Array.from(input.selectedOptions).map(option => option.value);
3377
- }
3378
- return input.value;
3379
- }
3380
- return input.value;
3381
- }
3382
- function parseFixedPrecision(type) {
3383
- const match = type.match(/^Fixed(?::(\d+))?$/);
3384
- if (match) {
3385
- return { precision: match[1] ? parseInt(match[1], 10) : 0 };
3386
- }
3387
- return {};
3388
- }
3389
- const TYPE_ALIASES = {
3390
- boolean: 'Boolean',
3391
- bool: 'Boolean',
3392
- string: 'String',
3393
- str: 'String',
3394
- number: 'Number',
3395
- num: 'Number',
3396
- int: 'Int',
3397
- integer: 'Int',
3398
- float: 'Float',
3399
- array: 'Array',
3400
- object: 'Object',
3401
- obj: 'Object',
3402
- date: 'Date',
3403
- json: 'JSON',
3404
- jsonstring: 'JSONString',
3405
- formencoded: 'FormEncoded',
3406
- };
3407
- function convertValue(value, type, context) {
3408
- if (typeof type !== 'string') {
3409
- throw new Error('Conversion type must be a string');
3410
- }
3411
- if (type.startsWith('Fixed')) {
3412
- const { precision } = parseFixedPrecision(type);
3413
- const num = defaultConversions.Number(value);
3414
- return num.toFixed(precision ?? 0);
3415
- }
3416
- if (value == null) {
3417
- return value;
3418
- }
3419
- let converter = defaultConversions[type];
3420
- if (converter) {
3421
- return converter(value, context);
3422
- }
3423
- const aliasedType = TYPE_ALIASES[type.toLowerCase()];
3424
- if (aliasedType) {
3425
- converter = defaultConversions[aliasedType];
3426
- if (converter) {
3427
- return converter(value, context);
3428
- }
3429
- }
3430
- const named = conversionConfig.conversions[type];
3431
- if (typeof named === 'function') {
3432
- return named(value, context);
3433
- }
3434
- for (const resolver of conversionConfig.conversions.dynamicResolvers) {
3435
- const resolved = resolver(type, value);
3436
- if (resolved !== undefined) {
3437
- return resolved;
3438
- }
3439
- }
3440
- console.warn(`Unknown conversion type: ${type}`);
3441
- return value;
3442
- }
3443
- const asExpression = {
3444
- name: 'as',
3445
- category: 'Conversion',
3446
- evaluatesTo: 'Any',
3447
- precedence: 20,
3448
- associativity: 'Left',
3449
- operators: ['as'],
3450
- async evaluate(context, ...args) {
3451
- const [value, type] = args;
3452
- return convertValue(value, type, context);
3453
- },
3454
- validate(args) {
3455
- return (validateArgCount(args, 2, 'as', 'value, type') ??
3456
- validateArgIsString(args, 1, 'as', 'conversion type'));
3457
- },
3458
- };
3459
- const isExpression = {
3460
- name: 'is',
3461
- category: 'Conversion',
3462
- evaluatesTo: 'Boolean',
3463
- precedence: 10,
3464
- associativity: 'Left',
3465
- operators: ['is a', 'is an'],
3466
- async evaluate(_context, ...args) {
3467
- const [value, type] = args;
3468
- if (!isString(type)) {
3469
- throw new Error('Type check requires a string type');
3470
- }
3471
- switch (type.toLowerCase()) {
3472
- case 'null':
3473
- return value === null;
3474
- case 'undefined':
3475
- return value === undefined;
3476
- case 'string':
3477
- return isString(value);
3478
- case 'number':
3479
- return isNumber(value) && !isNaN(value);
3480
- case 'boolean':
3481
- return isBoolean(value);
3482
- case 'object':
3483
- return isObject(value);
3484
- case 'array':
3485
- return Array.isArray(value);
3486
- case 'function':
3487
- return isFunction(value);
3488
- case 'date':
3489
- return value instanceof Date;
3490
- case 'element':
3491
- return value instanceof Element;
3492
- case 'node':
3493
- return value instanceof Node;
3494
- case 'nodelist':
3495
- return value instanceof NodeList;
3496
- case 'empty':
3497
- return (value == null ||
3498
- value === '' ||
3499
- (Array.isArray(value) && value.length === 0) ||
3500
- (isObject(value) && Object.keys(value).length === 0));
3501
- default:
3502
- return value?.constructor?.name?.toLowerCase() === type.toLowerCase();
3503
- }
3504
- },
3505
- validate(args) {
3506
- return (validateArgCount(args, 2, 'is', 'value, type') ?? validateArgIsString(args, 1, 'is', 'type'));
3507
- },
3508
- };
3509
- const asyncExpression = {
3510
- name: 'async',
3511
- category: 'Conversion',
3512
- evaluatesTo: 'Any',
3513
- precedence: 25,
3514
- associativity: 'Right',
3515
- operators: ['async'],
3516
- async evaluate(_context, expression) {
3517
- return expression;
3518
- },
3519
- validate(args) {
3520
- return validateArgCount(args, 1, 'async', 'expression');
3521
- },
3522
- };
3523
- const conversionExpressions = {
3524
- as: asExpression,
3525
- is: isExpression,
3526
- async: asyncExpression,
3527
- };
3528
-
3529
- const firstExpression = {
3530
- name: 'first',
3531
- category: 'Reference',
3532
- evaluatesTo: 'Any',
3533
- operators: ['first'],
3534
- async evaluate(context, collection) {
3535
- const target = collection !== undefined ? collection : context.it;
3536
- if (target == null) {
3537
- return null;
3538
- }
3539
- if (Array.isArray(target)) {
3540
- return target.length > 0 ? target[0] : null;
3541
- }
3542
- if (target instanceof NodeList || target instanceof HTMLCollection) {
3543
- return target.length > 0 ? target[0] : null;
3544
- }
3545
- if (target instanceof Element) {
3546
- return target.children.length > 0 ? target.children[0] : null;
3547
- }
3548
- if (isString(target)) {
3549
- const strTarget = target;
3550
- return strTarget.length > 0 ? strTarget[0] : null;
3551
- }
3552
- if (isObject(target) && 'length' in target && isNumber(target.length)) {
3553
- const objTarget = target;
3554
- return objTarget.length > 0 ? objTarget[0] : null;
3555
- }
3556
- return null;
3557
- },
3558
- validate(args) {
3559
- return validateMaxArgs(args, 1, 'first', 'collection');
3560
- },
3561
- };
3562
- const lastExpression = {
3563
- name: 'last',
3564
- category: 'Reference',
3565
- evaluatesTo: 'Any',
3566
- operators: ['last'],
3567
- async evaluate(context, collection) {
3568
- const target = collection !== undefined ? collection : context.it;
3569
- if (target == null) {
3570
- return null;
3571
- }
3572
- if (Array.isArray(target)) {
3573
- return target.length > 0 ? target[target.length - 1] : null;
3574
- }
3575
- if (target instanceof NodeList || target instanceof HTMLCollection) {
3576
- return target.length > 0 ? target[target.length - 1] : null;
3577
- }
3578
- if (target instanceof Element) {
3579
- const children = target.children;
3580
- return children.length > 0 ? children[children.length - 1] : null;
3581
- }
3582
- if (isString(target)) {
3583
- const strTarget = target;
3584
- return strTarget.length > 0 ? strTarget[strTarget.length - 1] : null;
3585
- }
3586
- if (isObject(target) && 'length' in target && isNumber(target.length)) {
3587
- const objTarget = target;
3588
- return objTarget.length > 0 ? objTarget[objTarget.length - 1] : null;
3589
- }
3590
- return null;
3591
- },
3592
- validate(args) {
3593
- return validateMaxArgs(args, 1, 'last', 'collection');
3594
- },
3595
- };
3596
- const atExpression = {
3597
- name: 'at',
3598
- category: 'Reference',
3599
- evaluatesTo: 'Any',
3600
- operators: ['at'],
3601
- async evaluate(context, ...args) {
3602
- const [index, collection] = args;
3603
- if (!isNumber(index)) {
3604
- throw new Error('Index must be a number');
3605
- }
3606
- const numIndex = index;
3607
- const target = collection !== undefined ? collection : context.it;
3608
- if (target == null) {
3609
- return null;
3610
- }
3611
- if (Array.isArray(target)) {
3612
- const actualIndex = numIndex < 0 ? target.length + numIndex : numIndex;
3613
- return actualIndex >= 0 && actualIndex < target.length ? target[actualIndex] : null;
3614
- }
3615
- if (target instanceof NodeList || target instanceof HTMLCollection) {
3616
- const actualIndex = numIndex < 0 ? target.length + numIndex : numIndex;
3617
- return actualIndex >= 0 && actualIndex < target.length ? target[actualIndex] : null;
3618
- }
3619
- if (target instanceof Element) {
3620
- const children = target.children;
3621
- const actualIndex = numIndex < 0 ? children.length + numIndex : numIndex;
3622
- return actualIndex >= 0 && actualIndex < children.length ? children[actualIndex] : null;
3623
- }
3624
- if (isString(target)) {
3625
- const strTarget = target;
3626
- const actualIndex = numIndex < 0 ? strTarget.length + numIndex : numIndex;
3627
- return actualIndex >= 0 && actualIndex < strTarget.length ? strTarget[actualIndex] : null;
3628
- }
3629
- if (isObject(target) && 'length' in target && isNumber(target.length)) {
3630
- const objTarget = target;
3631
- const actualIndex = numIndex < 0 ? objTarget.length + numIndex : numIndex;
3632
- return actualIndex >= 0 && actualIndex < objTarget.length ? objTarget[actualIndex] : null;
3633
- }
3634
- return null;
3635
- },
3636
- validate(args) {
3637
- return (validateArgRange(args, 1, 2, 'at', 'index, optional collection') ??
3638
- validateArgIsNumber(args, 0, 'at', 'index'));
3639
- },
3640
- };
3641
- const nextExpression = {
3642
- name: 'next',
3643
- category: 'Reference',
3644
- evaluatesTo: 'Element',
3645
- operators: ['next'],
3646
- async evaluate(context, ...args) {
3647
- const [selector, fromElement, options] = args;
3648
- const startElement = fromElement || context.me;
3649
- if (!startElement || !(startElement instanceof Element)) {
3650
- return null;
3651
- }
3652
- if (!selector) {
3653
- return startElement.nextElementSibling;
3654
- }
3655
- if (options) {
3656
- return scanRelative(startElement, selector, options, true);
3657
- }
3658
- return findNextElementInDOM(startElement, selector);
3659
- },
3660
- validate(args) {
3661
- const maxError = validateMaxArgs(args, 3, 'next', 'optional selector, optional fromElement, optional modifiers');
3662
- if (maxError)
3663
- return maxError;
3664
- if (args.length >= 1 && args[0] != null && typeof args[0] !== 'string') {
3665
- return 'selector must be a string';
3666
- }
3667
- if (args.length >= 2 && args[1] != null && !(args[1] instanceof Element)) {
3668
- return 'fromElement must be an Element';
3669
- }
3670
- return null;
3671
- },
3672
- };
3673
- const previousExpression = {
3674
- name: 'previous',
3675
- category: 'Reference',
3676
- evaluatesTo: 'Element',
3677
- operators: ['previous', 'prev'],
3678
- async evaluate(context, ...args) {
3679
- const [selector, fromElement, options] = args;
3680
- const startElement = fromElement || context.me;
3681
- if (!startElement || !(startElement instanceof Element)) {
3682
- return null;
3683
- }
3684
- if (!selector) {
3685
- return startElement.previousElementSibling;
3686
- }
3687
- if (options) {
3688
- return scanRelative(startElement, selector, options, false);
3689
- }
3690
- return findPreviousElementInDOM(startElement, selector);
3691
- },
3692
- validate(args) {
3693
- const maxError = validateMaxArgs(args, 3, 'previous', 'optional selector, optional fromElement, optional modifiers');
3694
- if (maxError)
3695
- return maxError;
3696
- if (args.length >= 1 && args[0] != null && typeof args[0] !== 'string') {
3697
- return 'selector must be a string';
3698
- }
3699
- if (args.length >= 2 && args[1] != null && !(args[1] instanceof Element)) {
3700
- return 'fromElement must be an Element';
3701
- }
3702
- return null;
3703
- },
3704
- };
3705
- function findNextElementInDOM(startElement, selector) {
3706
- let current = startElement.nextElementSibling;
3707
- while (current) {
3708
- if (current.matches(selector)) {
3709
- return current;
3710
- }
3711
- const found = current.querySelector(selector);
3712
- if (found) {
3713
- return found;
3714
- }
3715
- current = current.nextElementSibling;
3716
- }
3717
- const parent = startElement.parentElement;
3718
- if (parent && parent !== document.documentElement) {
3719
- return findNextElementInDOM(parent, selector);
3720
- }
3721
- return null;
3722
- }
3723
- function findPreviousElementInDOM(startElement, selector) {
3724
- let current = startElement.previousElementSibling;
3725
- while (current) {
3726
- const descendants = Array.from(current.querySelectorAll(selector)).reverse();
3727
- if (descendants.length > 0) {
3728
- return descendants[0];
3729
- }
3730
- if (current.matches(selector)) {
3731
- return current;
3732
- }
3733
- current = current.previousElementSibling;
3734
- }
3735
- const parent = startElement.parentElement;
3736
- if (parent && parent !== document.documentElement) {
3737
- return findPreviousElementInDOM(parent, selector);
3738
- }
3739
- return null;
3740
- }
3741
- const DOCUMENT_POSITION_PRECEDING = 2;
3742
- const DOCUMENT_POSITION_FOLLOWING = 4;
3743
- function scanForwardQuery(start, root, match, wrap) {
3744
- const results = root.querySelectorAll(match);
3745
- for (let i = 0; i < results.length; i++) {
3746
- const elt = results[i];
3747
- if (elt.compareDocumentPosition(start) === DOCUMENT_POSITION_PRECEDING) {
3748
- return elt;
3749
- }
3750
- }
3751
- return wrap ? results[0] : undefined;
3752
- }
3753
- function scanBackwardsQuery(start, root, match, wrap) {
3754
- const results = root.querySelectorAll(match);
3755
- for (let i = results.length - 1; i >= 0; i--) {
3756
- const elt = results[i];
3757
- if (elt.compareDocumentPosition(start) === DOCUMENT_POSITION_FOLLOWING) {
3758
- return elt;
3759
- }
3760
- }
3761
- return wrap ? results[results.length - 1] : undefined;
3762
- }
3763
- function scanForwardArray(start, arrayLike, match, wrap) {
3764
- const array = Array.from(arrayLike ?? []);
3765
- const matches = [];
3766
- for (const elt of array) {
3767
- if ((elt.matches && elt.matches(match)) || elt === start) {
3768
- matches.push(elt);
3769
- }
3770
- }
3771
- for (let i = 0; i < matches.length - 1; i++) {
3772
- if (matches[i] === start) {
3773
- return matches[i + 1];
3774
- }
3775
- }
3776
- if (wrap) {
3777
- const first = matches[0];
3778
- if (first && first.matches && first.matches(match)) {
3779
- return first;
3780
- }
3781
- }
3782
- return undefined;
3783
- }
3784
- function scanRelative(start, selector, options, forward) {
3785
- if (options.inSearch) {
3786
- if (options.inElt == null)
3787
- return undefined;
3788
- const array = forward
3789
- ? Array.from(options.inElt)
3790
- : Array.from(options.inElt).reverse();
3791
- return scanForwardArray(start, array, selector, !!options.wrapping);
3792
- }
3793
- const root = options.within ?? (typeof document !== 'undefined' ? document.body : null);
3794
- if (!root)
3795
- return undefined;
3796
- return forward
3797
- ? scanForwardQuery(start, root, selector, !!options.wrapping)
3798
- : scanBackwardsQuery(start, root, selector, !!options.wrapping);
3799
- }
3800
- const nextWithinExpression = {
3801
- name: 'nextWithin',
3802
- category: 'Reference',
3803
- evaluatesTo: 'Element',
3804
- operators: ['next within'],
3805
- async evaluate(context, ...args) {
3806
- const [selector, withinSelector, fromElement] = args;
3807
- const startElement = fromElement || context.me;
3808
- if (!startElement || !(startElement instanceof Element)) {
3809
- return null;
3810
- }
3811
- const container = startElement.closest(withinSelector);
3812
- if (!container) {
3813
- return null;
3814
- }
3815
- return findNextElementWithinContainer(startElement, selector, container);
3816
- },
3817
- validate(args) {
3818
- const rangeError = validateArgRange(args, 2, 3, 'nextWithin', 'selector, withinSelector, optional fromElement');
3819
- if (rangeError)
3820
- return rangeError;
3821
- if (typeof args[0] !== 'string') {
3822
- return 'selector must be a string';
3823
- }
3824
- if (typeof args[1] !== 'string') {
3825
- return 'withinSelector must be a string';
3826
- }
3827
- if (args.length >= 3 && args[2] != null && !(args[2] instanceof Element)) {
3828
- return 'fromElement must be an Element';
3829
- }
3830
- return null;
3831
- },
3832
- };
3833
- const previousWithinExpression = {
3834
- name: 'previousWithin',
3835
- category: 'Reference',
3836
- evaluatesTo: 'Element',
3837
- operators: ['previous within'],
3838
- async evaluate(context, ...args) {
3839
- const [selector, withinSelector, fromElement] = args;
3840
- const startElement = fromElement || context.me;
3841
- if (!startElement || !(startElement instanceof Element)) {
3842
- return null;
3843
- }
3844
- const container = startElement.closest(withinSelector);
3845
- if (!container) {
3846
- return null;
3847
- }
3848
- return findPreviousElementWithinContainer(startElement, selector, container);
3849
- },
3850
- validate(args) {
3851
- const rangeError = validateArgRange(args, 2, 3, 'previousWithin', 'selector, withinSelector, optional fromElement');
3852
- if (rangeError)
3853
- return rangeError;
3854
- if (typeof args[0] !== 'string') {
3855
- return 'selector must be a string';
3856
- }
3857
- if (typeof args[1] !== 'string') {
3858
- return 'withinSelector must be a string';
3859
- }
3860
- if (args.length >= 3 && args[2] != null && !(args[2] instanceof Element)) {
3861
- return 'fromElement must be an Element';
3862
- }
3863
- return null;
3864
- },
3865
- };
3866
- function findNextElementWithinContainer(startElement, selector, container) {
3867
- const matches = Array.from(container.querySelectorAll(selector));
3868
- const startPosition = getElementPosition(startElement);
3869
- for (const element of matches) {
3870
- const position = getElementPosition(element);
3871
- if (position > startPosition) {
3872
- return element;
3873
- }
3874
- }
3875
- return null;
3876
- }
3877
- function findPreviousElementWithinContainer(startElement, selector, container) {
3878
- const matches = Array.from(container.querySelectorAll(selector));
3879
- const startPosition = getElementPosition(startElement);
3880
- for (let i = matches.length - 1; i >= 0; i--) {
3881
- const element = matches[i];
3882
- const position = getElementPosition(element);
3883
- if (position < startPosition) {
3884
- return element;
3885
- }
3886
- }
3887
- return null;
3888
- }
3889
- function getElementPosition(element) {
3890
- let position = 0;
3891
- let current = element;
3892
- while (current && current.parentElement) {
3893
- const siblings = Array.from(current.parentElement.children);
3894
- position += siblings.indexOf(current);
3895
- current = current.parentElement;
3896
- position += 1000;
3897
- }
3898
- return position;
3899
- }
3900
- const positionalExpressions = {
3901
- first: firstExpression,
3902
- last: lastExpression,
3903
- at: atExpression,
3904
- next: nextExpression,
3905
- previous: previousExpression,
3906
- nextWithin: nextWithinExpression,
3907
- previousWithin: previousWithinExpression,
3908
- };
3909
-
3910
- function createCommonRegistry() {
3911
- return createExpressionRegistry(referencesExpressions, logicalExpressions, specialExpressions, mathematicalExpressions, conversionExpressions, positionalExpressions);
3912
- }
3913
-
3914
- function isInputElement(el) {
3915
- return (el !== null && typeof el === 'object' && 'tagName' in el && el.tagName === 'INPUT');
3916
- }
3917
- function isHTMLElement$1(el) {
3918
- return (el !== null &&
3919
- typeof el === 'object' &&
3920
- 'nodeType' in el &&
3921
- el.nodeType === 1 &&
3922
- 'style' in el);
3923
- }
3924
- function isOptionElement(el) {
3925
- return (el !== null &&
3926
- typeof el !== 'undefined' &&
3927
- typeof el === 'object' &&
3928
- 'tagName' in el &&
3929
- el.tagName === 'OPTION');
3930
- }
3931
-
3932
- function isHTMLElement(value) {
3933
- return value instanceof HTMLElement;
3934
- }
3935
- const BOOLEAN_ATTRIBUTES = new Set([
3936
- 'disabled',
3937
- 'readonly',
3938
- 'required',
3939
- 'checked',
3940
- 'selected',
3941
- 'hidden',
3942
- 'open',
3943
- 'autofocus',
3944
- 'autoplay',
3945
- 'controls',
3946
- 'loop',
3947
- 'muted',
3948
- 'multiple',
3949
- 'reversed',
3950
- 'defer',
3951
- 'async',
3952
- 'novalidate',
3953
- 'formnovalidate',
3954
- 'ismap',
3955
- ]);
3956
- function accessAttribute(element, attrName) {
3957
- if (BOOLEAN_ATTRIBUTES.has(attrName.toLowerCase())) {
3958
- return element.hasAttribute(attrName);
3959
- }
3960
- return element.getAttribute(attrName);
3961
- }
3962
- function hasAttribute(element, attrName) {
3963
- return element.hasAttribute(attrName);
3964
- }
3965
- const SPECIAL_DOM_PROPERTIES = {
3966
- id: el => el.id,
3967
- classname: el => el.className,
3968
- class: el => el.className,
3969
- tagname: el => el.tagName.toLowerCase(),
3970
- innertext: el => el.textContent?.trim(),
3971
- innerHTML: el => el.innerHTML,
3972
- outerhtml: el => el.outerHTML,
3973
- value: el => ('value' in el ? el.value : undefined),
3974
- checked: el => (isInputElement(el) ? el.checked : undefined),
3975
- disabled: el => ('disabled' in el ? el.disabled : undefined),
3976
- selected: el => (isOptionElement(el) ? el.selected : undefined),
3977
- tabindex: el => (isHTMLElement$1(el) ? el.tabIndex : undefined),
3978
- hidden: el => (isHTMLElement$1(el) ? el.hidden : undefined),
3979
- style: el => getComputedStyle(el),
3980
- children: el => Array.from(el.children),
3981
- parent: el => el.parentElement,
3982
- firstchild: el => el.firstElementChild,
3983
- lastchild: el => el.lastElementChild,
3984
- nextsibling: el => el.nextElementSibling,
3985
- previoussibling: el => el.previousElementSibling,
3986
- next: el => el.nextElementSibling,
3987
- previous: el => el.previousElementSibling,
3988
- values: el => collectFormValues(el),
3989
- };
3990
- function collectFormValues(el) {
3991
- if (el instanceof HTMLFormElement)
3992
- return new FormData(el);
3993
- const fd = new FormData();
3994
- el.querySelectorAll('input, select, textarea').forEach((input) => {
3995
- const name = input.getAttribute('name');
3996
- if (name && 'value' in input)
3997
- fd.append(name, input.value);
3998
- });
3999
- return fd;
4000
- }
4001
- function getElementStyleValue(element, styleProp) {
4002
- if (!isHTMLElement(element))
4003
- return undefined;
4004
- if (styleProp.startsWith('computed-')) {
4005
- return getComputedStyle(element).getPropertyValue(styleProp.slice('computed-'.length)) || '';
4006
- }
4007
- const camel = styleProp.replace(/-([a-z])/g, (_m, c) => c.toUpperCase());
4008
- return element.style[camel];
4009
- }
4010
- function getElementProperty(element, property) {
4011
- if (property.startsWith('*')) {
4012
- return getElementStyleValue(element, property.slice(1));
4013
- }
4014
- if (property.startsWith('computed-')) {
4015
- const cssProperty = property.slice('computed-'.length);
4016
- if (isHTMLElement(element)) {
4017
- const computedStyle = getComputedStyle(element);
4018
- return computedStyle.getPropertyValue(cssProperty);
4019
- }
4020
- return undefined;
4021
- }
4022
- if (property.startsWith('@')) {
4023
- const attrName = property.slice(1);
4024
- return accessAttribute(element, attrName);
4025
- }
4026
- const specialHandler = SPECIAL_DOM_PROPERTIES[property.toLowerCase()];
4027
- if (specialHandler) {
4028
- return specialHandler(element);
4029
- }
4030
- if (hasAttribute(element, property)) {
4031
- return accessAttribute(element, property);
4032
- }
4033
- const value = element[property];
4034
- if (isFunction(value)) {
4035
- return value.bind(element);
4036
- }
4037
- return value;
4038
- }
4039
-
4040
- const UNSAFE_PROPS = new Set(['__proto__', 'constructor', 'prototype']);
4041
- function readPossessiveValue(element, property) {
4042
- if (element instanceof Element) {
4043
- return getElementProperty(element, property);
4044
- }
4045
- if (isObject(element)) {
4046
- if (UNSAFE_PROPS.has(property))
4047
- return undefined;
4048
- return element[property];
4049
- }
4050
- return element[property];
4051
- }
4052
- function isMappableCollection(v) {
4053
- let items;
4054
- if (Array.isArray(v)) {
4055
- items = v;
4056
- }
4057
- else if ((typeof NodeList !== 'undefined' && v instanceof NodeList) ||
4058
- (typeof HTMLCollection !== 'undefined' && v instanceof HTMLCollection)) {
4059
- items = Array.from(v);
4060
- }
4061
- else {
4062
- return false;
4063
- }
4064
- if (items.length === 0)
4065
- return false;
4066
- return items.every(item => item instanceof Element ||
4067
- (item != null &&
4068
- typeof item === 'object' &&
4069
- item.constructor !== Object &&
4070
- !Array.isArray(item)));
4071
- }
4072
- const possessiveExpression = {
4073
- name: 'possessive',
4074
- category: 'Reference',
4075
- evaluatesTo: 'Any',
4076
- operators: ["'s", 's'],
4077
- async evaluate(_context, ...args) {
4078
- const [element, property] = args;
4079
- if (element == null) {
4080
- return undefined;
4081
- }
4082
- if (typeof property !== 'string') {
4083
- throw new Error('Property name must be a string');
4084
- }
4085
- if (isMappableCollection(element) && !(property in element)) {
4086
- return Array.from(element, item => readPossessiveValue(item, property));
4087
- }
4088
- return readPossessiveValue(element, property);
4089
- },
4090
- validate(args) {
4091
- return (validateArgCount(args, 2, 'possessive', 'element, property') ??
4092
- validateArgIsString(args, 1, 'possessive', 'property name'));
4093
- },
4094
- };
4095
- const myExpression = {
4096
- name: 'my',
4097
- category: 'Reference',
4098
- evaluatesTo: 'Any',
4099
- operators: ['my'],
4100
- async evaluate(context, ...args) {
4101
- const [property] = args;
4102
- if (!context.me) {
4103
- return undefined;
4104
- }
4105
- if (typeof property !== 'string') {
4106
- throw new Error('Property name must be a string');
4107
- }
4108
- if (context.me instanceof Element) {
4109
- return getElementProperty(context.me, property);
4110
- }
4111
- if (isObject(context.me)) {
4112
- if (UNSAFE_PROPS.has(property))
4113
- return undefined;
4114
- return context.me[property];
4115
- }
4116
- return context.me[property];
4117
- },
4118
- validate(args) {
4119
- return validateSingleStringArg(args, 'my', 'property');
4120
- },
4121
- };
4122
- const itsExpression = {
4123
- name: 'its',
4124
- category: 'Reference',
4125
- evaluatesTo: 'Any',
4126
- operators: ['its'],
4127
- async evaluate(context, ...args) {
4128
- const [property] = args;
4129
- if (context.it == null) {
4130
- return undefined;
4131
- }
4132
- if (typeof property !== 'string') {
4133
- throw new Error('Property name must be a string');
4134
- }
4135
- const target = context.it;
4136
- if (target instanceof Element) {
4137
- return getElementProperty(target, property);
4138
- }
4139
- if (isObject(target)) {
4140
- if (UNSAFE_PROPS.has(property))
4141
- return undefined;
4142
- return target[property];
4143
- }
4144
- return target[property];
4145
- },
4146
- validate(args) {
4147
- return validateSingleStringArg(args, 'its', 'property');
4148
- },
4149
- };
4150
- const yourExpression = {
4151
- name: 'your',
4152
- category: 'Reference',
4153
- evaluatesTo: 'Any',
4154
- operators: ['your'],
4155
- async evaluate(context, ...args) {
4156
- const [property] = args;
4157
- if (!context.you) {
4158
- return undefined;
4159
- }
4160
- if (typeof property !== 'string') {
4161
- throw new Error('Property name must be a string');
4162
- }
4163
- if (context.you instanceof Element) {
4164
- return getElementProperty(context.you, property);
4165
- }
4166
- if (isObject(context.you)) {
4167
- if (UNSAFE_PROPS.has(property))
4168
- return undefined;
4169
- return context.you[property];
4170
- }
4171
- return context.you[property];
4172
- },
4173
- validate(args) {
4174
- return validateSingleStringArg(args, 'your', 'property');
4175
- },
4176
- };
4177
- const ofExpression = {
4178
- name: 'of',
4179
- category: 'Reference',
4180
- evaluatesTo: 'Any',
4181
- operators: ['of'],
4182
- async evaluate(_context, ...args) {
4183
- const [property, object] = args;
4184
- if (object == null) {
4185
- return undefined;
4186
- }
4187
- if (typeof property !== 'string') {
4188
- throw new Error('Property name must be a string');
4189
- }
4190
- if (object instanceof Element) {
4191
- return getElementProperty(object, property);
4192
- }
4193
- if (isObject(object)) {
4194
- if (UNSAFE_PROPS.has(property))
4195
- return undefined;
4196
- return object[property];
4197
- }
4198
- return object[property];
4199
- },
4200
- validate(args) {
4201
- return (validateArgCount(args, 2, 'of', 'property, object') ??
4202
- validateArgIsString(args, 0, 'of', 'property name'));
4203
- },
4204
- };
4205
- const attributeExpression = {
4206
- name: 'attribute',
4207
- category: 'Reference',
4208
- evaluatesTo: 'String',
4209
- operators: ['@'],
4210
- async evaluate(context, ...args) {
4211
- const [attributeName, element] = args;
4212
- if (typeof attributeName !== 'string') {
4213
- throw new Error('Attribute name must be a string');
4214
- }
4215
- const target = element || context.me;
4216
- if (!target || !(target instanceof Element)) {
4217
- return null;
4218
- }
4219
- return target.getAttribute(attributeName);
4220
- },
4221
- validate(args) {
4222
- return (validateArgRange(args, 1, 2, 'attribute', 'attributeName, optional element') ??
4223
- validateArgIsString(args, 0, 'attribute', 'attribute name') ??
4224
- (args.length >= 2 && args[1] != null && !(args[1] instanceof Element)
4225
- ? 'attribute element must be an Element'
4226
- : null));
4227
- },
4228
- };
4229
- const attributeWithValueExpression = {
4230
- name: 'attributeWithValue',
4231
- category: 'Reference',
4232
- evaluatesTo: 'Boolean',
4233
- operators: ['@='],
4234
- async evaluate(context, ...args) {
4235
- const [attributeName, expectedValue, element] = args;
4236
- if (typeof attributeName !== 'string') {
4237
- throw new Error('Attribute name must be a string');
4238
- }
4239
- if (typeof expectedValue !== 'string') {
4240
- throw new Error('Expected value must be a string');
4241
- }
4242
- const target = element || context.me;
4243
- if (!target || !(target instanceof Element)) {
4244
- return false;
4245
- }
4246
- const actualValue = target.getAttribute(attributeName);
4247
- return actualValue === expectedValue;
4248
- },
4249
- validate(args) {
4250
- return (validateArgRange(args, 2, 3, 'attributeWithValue', 'attributeName, expectedValue, optional element') ??
4251
- validateArgIsString(args, 0, 'attributeWithValue', 'attribute name') ??
4252
- validateArgIsString(args, 1, 'attributeWithValue', 'expected value') ??
4253
- (args.length >= 3 && args[2] != null && !(args[2] instanceof Element)
4254
- ? 'attributeWithValue element must be an Element'
4255
- : null));
4256
- },
4257
- };
4258
- const classReferenceExpression = {
4259
- name: 'classReference',
4260
- category: 'Reference',
4261
- evaluatesTo: 'Array',
4262
- operators: ['.'],
4263
- async evaluate(_context, ...args) {
4264
- const [className] = args;
4265
- if (typeof className !== 'string') {
4266
- throw new Error('Class name must be a string');
4267
- }
4268
- const cleanClassName = className.startsWith('.') ? className.slice(1) : className;
4269
- const elements = document.getElementsByClassName(cleanClassName);
4270
- return Array.from(elements);
4271
- },
4272
- validate(args) {
4273
- return validateSingleStringArg(args, 'classReference', 'className');
4274
- },
4275
- };
4276
- const idReferenceExpression = {
4277
- name: 'idReference',
4278
- category: 'Reference',
4279
- evaluatesTo: 'Element',
4280
- operators: ['#'],
4281
- async evaluate(_context, ...args) {
4282
- const [idValue] = args;
4283
- if (typeof idValue !== 'string') {
4284
- throw new Error('ID value must be a string');
4285
- }
4286
- const cleanId = idValue.startsWith('#') ? idValue.slice(1) : idValue;
4287
- return document.getElementById(cleanId);
4288
- },
4289
- validate(args) {
4290
- return validateSingleStringArg(args, 'idReference', 'idValue');
4291
- },
4292
- };
4293
- const propertiesExpressions = {
4294
- possessive: possessiveExpression,
4295
- my: myExpression,
4296
- its: itsExpression,
4297
- your: yourExpression,
4298
- of: ofExpression,
4299
- attribute: attributeExpression,
4300
- attributeWithValue: attributeWithValueExpression,
4301
- classReference: classReferenceExpression,
4302
- idReference: idReferenceExpression,
4303
- };
4304
-
4305
- function createFullRegistry() {
4306
- return createExpressionRegistry(referencesExpressions, logicalExpressions, specialExpressions, mathematicalExpressions, conversionExpressions, positionalExpressions, propertiesExpressions);
4307
- }
4308
-
4309
- function createFullExpressionRegistry() {
4310
- return createExpressionRegistry(referencesExpressions, logicalExpressions, conversionExpressions, positionalExpressions, propertiesExpressions, specialExpressions, mathematicalExpressions);
4311
- }
4312
-
4313
- exports.conversion = conversionExpressions;
4314
- exports.conversionExpressions = conversionExpressions;
4315
- exports.createCommonRegistry = createCommonRegistry;
4316
- exports.createCoreRegistry = createCoreRegistry;
4317
- exports.createExpressionRegistry = createExpressionRegistry;
4318
- exports.createFullExpressionRegistry = createFullExpressionRegistry;
4319
- exports.createFullRegistry = createFullRegistry;
4320
- exports.logical = logicalExpressions;
4321
- exports.logicalExpressions = logicalExpressions;
4322
- exports.mathematical = mathematicalExpressions;
4323
- exports.positional = positionalExpressions;
4324
- exports.positionalExpressions = positionalExpressions;
4325
- exports.properties = propertiesExpressions;
4326
- exports.propertiesExpressions = propertiesExpressions;
4327
- exports.references = referencesExpressions;
4328
- exports.referencesExpressions = referencesExpressions;
4329
- exports.special = specialExpressions;
4330
- exports.specialExpressions = specialExpressions;
4331
- //# sourceMappingURL=index.cjs.map