Step 18 (part 6): _hyperscript integration — _="..." attribute wiring
lib/hyperscript/integration.sx — connects compiled hyperscript to DOM: hs-handler(src) — compile source → callable (fn (me) ...) via eval-expr-cek hs-activate!(el) — read _="...", compile, execute with me=element hs-boot!() — scan document for [_] elements, activate all hs-boot-subtree!(root) — activate within subtree (for HTMX swaps) Handler wraps compiled SX in (fn (me) (let ((it nil) (event nil)) ...)) so each element gets its own me binding and clean it/event state. Double-activation prevented via data-hs-active marker. 12 integration tests verify full pipeline: source → compile → eval. Handlers correctly bind me, support arithmetic, conditionals, sequences, for loops, and repeat. 3111/3111 full build, zero regressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
66
lib/hyperscript/integration.sx
Normal file
66
lib/hyperscript/integration.sx
Normal file
@@ -0,0 +1,66 @@
|
||||
;; _hyperscript integration — wire _="..." attributes to compiled SX
|
||||
;;
|
||||
;; Entry points:
|
||||
;; (hs-handler src) — compile source to callable (fn (me) ...)
|
||||
;; (hs-activate! el) — activate hyperscript on a single element
|
||||
;; (hs-boot!) — scan DOM, activate all _="..." elements
|
||||
;; (hs-boot-subtree! root) — activate within a subtree (for HTMX swaps)
|
||||
|
||||
;; ── Compile source to a handler function ────────────────────────
|
||||
;; Returns a function (fn (me) ...) that can be called with a DOM element.
|
||||
;; Uses eval-expr-cek to turn the SX data structure into a live closure.
|
||||
|
||||
(define
|
||||
hs-handler
|
||||
(fn
|
||||
(src)
|
||||
(let
|
||||
((sx (hs-to-sx-from-source src)))
|
||||
(eval-expr-cek
|
||||
(list
|
||||
(quote fn)
|
||||
(list (quote me))
|
||||
(list
|
||||
(quote let)
|
||||
(list (list (quote it) nil) (list (quote event) nil))
|
||||
sx))))))
|
||||
|
||||
;; ── Activate a single element ───────────────────────────────────
|
||||
;; Reads the _="..." attribute, compiles, and executes with me=element.
|
||||
;; Marks the element to avoid double-activation.
|
||||
|
||||
(define
|
||||
hs-activate!
|
||||
(fn
|
||||
(el)
|
||||
(let
|
||||
((src (dom-get-attr el "_")))
|
||||
(when
|
||||
(and src (not (dom-get-data el "hs-active")))
|
||||
(dom-set-data el "hs-active" true)
|
||||
(let ((handler (hs-handler src))) (handler el))))))
|
||||
|
||||
;; ── Boot: scan entire document ──────────────────────────────────
|
||||
;; Called once at page load. Finds all elements with _ attribute,
|
||||
;; compiles their hyperscript, and activates them.
|
||||
|
||||
(define
|
||||
hs-boot!
|
||||
(fn
|
||||
()
|
||||
(let
|
||||
((elements (dom-query-all (dom-body) "[_]")))
|
||||
(for-each (fn (el) (hs-activate! el)) elements))))
|
||||
|
||||
;; ── Boot subtree: for dynamic content ───────────────────────────
|
||||
;; Called after HTMX swaps or dynamic DOM insertion.
|
||||
;; Only activates elements within the given root.
|
||||
|
||||
(define
|
||||
hs-boot-subtree!
|
||||
(fn
|
||||
(root)
|
||||
(let
|
||||
((elements (dom-query-all root "[_]")))
|
||||
(for-each (fn (el) (hs-activate! el)) elements))
|
||||
(when (dom-get-attr root "_") (hs-activate! root))))
|
||||
Reference in New Issue
Block a user