Fix stepper: lake SSR preservation + stack rebuild after stepping

Three fixes:

1. Framework: render-dom-lake preserves SSR elements during hydration.
   When client-side render-to-dom encounters a lake with an existing
   DOM element (from SSR), it reuses that element instead of creating
   a new one. This prevents the SSR HTML from being replaced with
   unresolvable raw SX expressions (~tw calls).

2. Stepper: skip rebuild-preview on initial hydration. Uses a non-
   reactive dict flag (not a signal) to avoid triggering the effect
   twice. On first run, just initializes the DOM stack from the
   existing SSR content by computing open-element depth from step
   types and walking lastElementChild.

3. Stepper: rebuild-preview computes correct DOM stack after re-render.
   Same depth computation + DOM walk approach. This fixes the bug where
   do-step after do-back would append elements to the wrong parent
   (e.g. "sx" span outside h1).

Also: increased code view font-size from 0.5rem to 0.85rem.

Playwright tests:
- lake never shows raw SX during hydration (mutation observer)
- back 6 + forward 6 keeps all 4 spans inside h1

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 15:18:16 +00:00
parent b13962e8dd
commit 547d271571
12 changed files with 69 additions and 103 deletions

View File

@@ -920,12 +920,17 @@
(dict "i" 0 "skip" false)
args)
(let
((el (dom-create-element lake-tag nil)))
(dom-set-attr el "data-sx-lake" (or lake-id ""))
(for-each
(fn (c) (dom-append el (render-to-dom c env ns)))
children)
el))))
((existing (when (and (client?) lake-id) (dom-query (str "[data-sx-lake=\"" lake-id "\"]")))))
(if
existing
existing
(let
((el (dom-create-element lake-tag nil)))
(dom-set-attr el "data-sx-lake" (or lake-id ""))
(for-each
(fn (c) (dom-append el (render-to-dom c env ns)))
children)
el))))))
(define
render-dom-marsh

File diff suppressed because one or more lines are too long

View File

@@ -49,7 +49,7 @@
"Other")))
(when
(not (has-key? categories category))
(dict-set! categories category (mutable-list)))
(dict-set! categories category (list)))
(append! (get categories category) {:doc (or (get kwargs "doc") "") :example (or (get kwargs "example") "") :tail-position (or (get kwargs "tail-position") "") :syntax (or (get kwargs "syntax") "") :name name}))))
parsed-exprs)
categories)))
@@ -200,7 +200,7 @@
(fn
((pages-raw :as list))
(let
((pages-data (mutable-list)) (client-count 0) (server-count 0))
((pages-data (list)) (client-count 0) (server-count 0))
(for-each
(fn
((page :as dict))

File diff suppressed because one or more lines are too long