diff --git a/shared/sx/helpers.py b/shared/sx/helpers.py index bd7aebe..fb4dd73 100644 --- a/shared/sx/helpers.py +++ b/shared/sx/helpers.py @@ -427,15 +427,20 @@ async def render_to_sx_with_env(__name: str, extra_env: dict, **kwargs: Any) -> """Like ``render_to_sx`` but merges *extra_env* into the evaluation environment before eval. Used by ``register_sx_layout`` so .sx defcomps can read ctx values as free variables. + + Uses ``async_eval_slot_to_sx`` (not ``async_eval_to_sx``) so the + top-level component body is expanded server-side — free variables + from *extra_env* are resolved during expansion rather than being + serialized as unresolved symbols for the client. """ from .jinja_bridge import get_component_env, _get_request_context - from .async_eval import async_eval_to_sx + from .async_eval import async_eval_slot_to_sx ast = _build_component_ast(__name, **kwargs) env = dict(get_component_env()) env.update(extra_env) ctx = _get_request_context() - return await async_eval_to_sx(ast, env, ctx) + return await async_eval_slot_to_sx(ast, env, ctx) async def render_to_sx(__name: str, **kwargs: Any) -> str: diff --git a/shared/sx/templates/layout.sx b/shared/sx/templates/layout.sx index 11b1dd4..b18bf7b 100644 --- a/shared/sx/templates/layout.sx +++ b/shared/sx/templates/layout.sx @@ -146,32 +146,24 @@ (when auth-menu (div :class "p-3 border-t border-stone-200" auth-menu)))) -;; --------------------------------------------------------------------------- -;; Root header/mobile wrappers — read ctx values from env free variables -;; Used by register_sx_layout so .sx defcomps compose without Python -;; --------------------------------------------------------------------------- - -(defcomp ~root-header (&key oob) - (~header-row-sx :cart-mini cart-mini :blog-url blog-url :site-title site-title - :app-label app-label :nav-tree nav-tree :auth-menu auth-menu - :nav-panel nav-panel :settings-url settings-url :is-admin is-admin - :oob oob)) - -(defcomp ~root-mobile () - (~mobile-root-nav :nav-tree nav-tree :auth-menu auth-menu)) - ;; --------------------------------------------------------------------------- ;; Built-in layout defcomps — used by register_sx_layout("root", ...) +;; Free variables (cart-mini, blog-url, etc.) come from _ctx_to_env(). ;; --------------------------------------------------------------------------- (defcomp ~layout-root-full () - (~root-header)) + (~header-row-sx :cart-mini cart-mini :blog-url blog-url :site-title site-title + :app-label app-label :nav-tree nav-tree :auth-menu auth-menu + :nav-panel nav-panel :settings-url settings-url :is-admin is-admin)) (defcomp ~layout-root-oob () - (~oob-header-sx :parent-id "root-header-child" :row (~root-header))) + (~oob-header-sx :parent-id "root-header-child" + :row (~header-row-sx :cart-mini cart-mini :blog-url blog-url :site-title site-title + :app-label app-label :nav-tree nav-tree :auth-menu auth-menu + :nav-panel nav-panel :settings-url settings-url :is-admin is-admin))) (defcomp ~layout-root-mobile () - (~root-mobile)) + (~mobile-root-nav :nav-tree nav-tree :auth-menu auth-menu)) (defcomp ~error-content (&key errnum message image) (div :class "text-center p-8 max-w-lg mx-auto"