Delete account/sx/sx_components.py — all rendering now in .sx
Phase 1 of zero-Python rendering: account service. - Auth pages (login, device, check-email) use _render_auth_page() helper calling render_to_sx() + full_page_sx() directly in routes - Newsletter toggle POST renders inline via render_to_sx() - Newsletter page helper returns data dict; defpage :data slot fetches, :content slot renders via ~account-newsletters-content defcomp - Fragment page uses (frag ...) IO primitive directly in .sx - Defpage _eval_slot now uses async_eval_slot_to_sx which expands component bodies server-side (executing IO) but serializes tags as SX - Fix pre-existing OOB ParseError: _eval_slot was producing HTML instead of s-expressions for component content slots - Fix market url_for endpoint: defpage_market_home (app-level, not blueprint) - Fix events calendar nav: wrap multiple SX parts in fragment Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -132,31 +132,14 @@ def load_page_dir(directory: str, service_name: str) -> list[PageDef]:
|
||||
# Page execution
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
async def _eval_slot(expr: Any, env: dict, ctx: Any,
|
||||
async_eval_fn: Any, async_eval_to_sx_fn: Any) -> str:
|
||||
async def _eval_slot(expr: Any, env: dict, ctx: Any) -> str:
|
||||
"""Evaluate a page slot expression and return an sx source string.
|
||||
|
||||
If the expression evaluates to a plain string (e.g. from a Python content
|
||||
builder), use it directly as sx source. If it evaluates to an AST/list,
|
||||
serialize it to sx wire format via async_eval_to_sx.
|
||||
Expands component calls (so IO in the body executes) but serializes
|
||||
the result as SX wire format, not HTML.
|
||||
"""
|
||||
from .html import _RawHTML
|
||||
from .parser import SxExpr
|
||||
# First try async_eval to get the raw value
|
||||
result = await async_eval_fn(expr, env, ctx)
|
||||
# If it's already an sx source string, use as-is
|
||||
if isinstance(result, str):
|
||||
return result
|
||||
if isinstance(result, _RawHTML):
|
||||
return result.html
|
||||
if isinstance(result, SxExpr):
|
||||
return result.source
|
||||
if result is None:
|
||||
return ""
|
||||
# For other types (lists, components rendered to HTML via _RawHTML, etc.),
|
||||
# serialize to sx wire format
|
||||
from .parser import serialize
|
||||
return serialize(result)
|
||||
from .async_eval import async_eval_slot_to_sx
|
||||
return await async_eval_slot_to_sx(expr, env, ctx)
|
||||
|
||||
|
||||
async def execute_page(
|
||||
@@ -174,7 +157,7 @@ async def execute_page(
|
||||
6. Branch: full_page_sx() vs oob_page_sx() based on is_htmx_request()
|
||||
"""
|
||||
from .jinja_bridge import get_component_env, _get_request_context
|
||||
from .async_eval import async_eval, async_eval_to_sx
|
||||
from .async_eval import async_eval
|
||||
from .page import get_template_context
|
||||
from .helpers import full_page_sx, oob_page_sx, sx_response
|
||||
from .layouts import get_layout
|
||||
@@ -204,20 +187,20 @@ async def execute_page(
|
||||
env.update(data_result)
|
||||
|
||||
# Render content slot (required)
|
||||
content_sx = await _eval_slot(page_def.content_expr, env, ctx, async_eval, async_eval_to_sx)
|
||||
content_sx = await _eval_slot(page_def.content_expr, env, ctx)
|
||||
|
||||
# Render optional slots
|
||||
filter_sx = ""
|
||||
if page_def.filter_expr is not None:
|
||||
filter_sx = await _eval_slot(page_def.filter_expr, env, ctx, async_eval, async_eval_to_sx)
|
||||
filter_sx = await _eval_slot(page_def.filter_expr, env, ctx)
|
||||
|
||||
aside_sx = ""
|
||||
if page_def.aside_expr is not None:
|
||||
aside_sx = await _eval_slot(page_def.aside_expr, env, ctx, async_eval, async_eval_to_sx)
|
||||
aside_sx = await _eval_slot(page_def.aside_expr, env, ctx)
|
||||
|
||||
menu_sx = ""
|
||||
if page_def.menu_expr is not None:
|
||||
menu_sx = await _eval_slot(page_def.menu_expr, env, ctx, async_eval, async_eval_to_sx)
|
||||
menu_sx = await _eval_slot(page_def.menu_expr, env, ctx)
|
||||
|
||||
# Resolve layout → header rows + mobile menu fallback
|
||||
tctx = await get_template_context()
|
||||
|
||||
Reference in New Issue
Block a user