Level 2-3: lake morphing — server content flows through reactive islands
Lake tag (lake :id "name" children...) creates server-morphable slots within islands. During morph, the engine enters hydrated islands and updates data-sx-lake elements by ID while preserving surrounding reactive DOM (signals, effects, event listeners). Specced in .sx, bootstrapped to JS and Python: - adapter-dom.sx: render-dom-lake, reactive-attr marks data-sx-reactive-attrs - adapter-html.sx: render-html-lake SSR output - adapter-sx.sx: lake serialized in wire format - engine.sx: morph-island-children (lake-by-ID matching), sync-attrs skips reactive attributes - ~sx-header uses lakes for logo and copyright - Hegelian essay updated with lake code example Also includes: lambda nil-padding for missing args, page env ordering fix Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,10 @@
|
||||
(= name "raw!")
|
||||
(join "" (map (fn (x) (str (trampoline (eval-expr x env)))) args))
|
||||
|
||||
;; Lake — server-morphable slot within an island
|
||||
(= name "lake")
|
||||
(render-html-lake args env)
|
||||
|
||||
;; HTML tag
|
||||
(contains? HTML_TAGS name)
|
||||
(render-html-element name args env)
|
||||
@@ -293,6 +297,43 @@
|
||||
"</" tag ">"))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; render-html-lake — SSR rendering of a server-morphable slot
|
||||
;; --------------------------------------------------------------------------
|
||||
;;
|
||||
;; (lake :id "name" children...) → <div data-sx-lake="name">children</div>
|
||||
;;
|
||||
;; Lakes are server territory inside islands. The morph can update lake
|
||||
;; content while preserving surrounding reactive DOM.
|
||||
|
||||
(define render-html-lake
|
||||
(fn (args env)
|
||||
(let ((lake-id nil)
|
||||
(lake-tag "div")
|
||||
(children (list)))
|
||||
(reduce
|
||||
(fn (state arg)
|
||||
(let ((skip (get state "skip")))
|
||||
(if skip
|
||||
(assoc state "skip" false "i" (inc (get state "i")))
|
||||
(if (and (= (type-of arg) "keyword")
|
||||
(< (inc (get state "i")) (len args)))
|
||||
(let ((kname (keyword-name arg))
|
||||
(kval (trampoline (eval-expr (nth args (inc (get state "i"))) env))))
|
||||
(cond
|
||||
(= kname "id") (set! lake-id kval)
|
||||
(= kname "tag") (set! lake-tag kval))
|
||||
(assoc state "skip" true "i" (inc (get state "i"))))
|
||||
(do
|
||||
(append! children arg)
|
||||
(assoc state "i" (inc (get state "i"))))))))
|
||||
(dict "i" 0 "skip" false)
|
||||
args)
|
||||
(str "<" lake-tag " data-sx-lake=\"" (escape-attr (or lake-id "")) "\">"
|
||||
(join "" (map (fn (c) (render-to-html c env)) children))
|
||||
"</" lake-tag ">"))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; render-html-island — SSR rendering of a reactive island
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user