sx-http: fix serialize_value + include all defines in component-defs

serialize_value: all lists emit (items...) not (list items...), matching
Python serialize() exactly. Empty lists emit (). This fixes let bindings,
fn params, and data structures for client-side parsing.

Component-defs now include named lambdas, macros, dicts, and other named
values from the env — client needs CSSX functions (cssx-process-token,
cssx-colour-props, cssx-spacing-props etc.) for island hydration.

Fixes: cssx-process-token, cssx-colour-props undefined errors.
Geography page: fully rendered with header island hydration working.
Homepage: nav renders, no error banners, stepper silent.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-28 19:04:54 +00:00
parent 900de713c3
commit 31ae9b5110

View File

@@ -53,14 +53,10 @@ let rec serialize_value = function
| Symbol s -> s
| Keyword k -> ":" ^ k
| List items | ListRef { contents = items } ->
(* Lists with a symbol head are call expressions: (fn arg1 arg2).
Lists starting with data values are data: (list 1 2 3).
This distinction matters for the client parser. *)
(match items with
| (Symbol _ | Keyword _) :: _ ->
"(" ^ String.concat " " (List.map serialize_value items) ^ ")"
| _ ->
"(list " ^ String.concat " " (List.map serialize_value items) ^ ")")
(* All lists: (items...) — no (list ...) wrapper.
Matches Python serialize() exactly. The SX source code itself uses
(list ...) where data lists are needed; the serializer preserves AST. *)
"(" ^ String.concat " " (List.map serialize_value items) ^ ")"
| Dict d ->
let pairs = Hashtbl.fold (fun k v acc ->
(Printf.sprintf ":%s %s" k (serialize_value v)) :: acc) d [] in
@@ -1635,7 +1631,8 @@ let read_css_file path =
let http_inject_shell_statics env static_dir sx_sxc =
(* Component definitions for client *)
let buf = Buffer.create 65536 in
Hashtbl.iter (fun _sym v ->
Hashtbl.iter (fun sym v ->
let name = Sx_types.unintern sym in
match v with
| Component c ->
let ps = String.concat " " (
@@ -1649,6 +1646,22 @@ let http_inject_shell_statics env static_dir sx_sxc =
(if i.i_has_children then ["&rest"; "children"] else [])) in
Buffer.add_string buf (Printf.sprintf "(defisland ~%s (%s) %s)\n"
i.i_name ps (serialize_value i.i_body))
| Lambda l when l.l_name <> None ->
(* Named lambdas — client needs utility functions like cssx-process-token *)
let fn_name = match l.l_name with Some n -> n | None -> name in
let ps = String.concat " " l.l_params in
Buffer.add_string buf (Printf.sprintf "(define %s (fn (%s) %s))\n"
fn_name ps (serialize_value l.l_body))
| Macro m ->
let ps = String.concat " " m.m_params in
let mname = match m.m_name with Some n -> n | None -> name in
Buffer.add_string buf (Printf.sprintf "(defmacro %s (%s) %s)\n"
mname ps (serialize_value m.m_body))
| Dict _ | Number _ | String _ | Bool _ | List _ | ListRef _ ->
(* Named values (dicts, lists, constants) — client needs CSSX config etc. *)
if String.length name > 0 && name.[0] <> '_' && name.[0] <> '*' then
Buffer.add_string buf (Printf.sprintf "(define %s %s)\n"
name (serialize_value v))
| _ -> ()
) env.bindings;
let raw_defs = Buffer.contents buf in