Make SxExpr a str subclass, sx_call/render functions return SxExpr
SxExpr is now a str subclass so it works everywhere a plain string does (join, isinstance, f-strings) while serialize() still emits it unquoted. sx_call() and all internal render functions (_render_to_sx, async_eval_to_sx, etc.) return SxExpr, eliminating the "forgot to wrap" bug class that caused the sx_content leak and list serialization bugs. - Phase 0: SxExpr(str) with .source property, __add__/__radd__ - Phase 1: sx_call returns SxExpr (drop-in, all 200+ sites unchanged) - Phase 2: async_eval_to_sx, async_eval_slot_to_sx, _render_to_sx, mobile_menu_sx return SxExpr; remove isinstance(str) workaround - Phase 3: Remove ~150 redundant SxExpr() wrappings across 45 files - Phase 4: serialize() docstring, handler return docs, ;; returns: sx Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -16,30 +16,27 @@ def _register_sx_layouts() -> None:
|
||||
async def _sx_full_headers(ctx: dict, **kw: Any) -> str:
|
||||
"""Full headers for sx home page: root + sx menu row."""
|
||||
from shared.sx.helpers import render_to_sx_with_env
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
main_nav = _main_nav_sx(kw.get("section"))
|
||||
sx_row = _sx_header_sx(main_nav)
|
||||
return await render_to_sx_with_env("sx-layout-full", {},
|
||||
sx_row=SxExpr(sx_row))
|
||||
sx_row=sx_row)
|
||||
|
||||
|
||||
async def _sx_oob_headers(ctx: dict, **kw: Any) -> str:
|
||||
"""OOB headers for sx home page."""
|
||||
from shared.sx.helpers import render_to_sx_with_env, oob_header_sx
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
main_nav = _main_nav_sx(kw.get("section"))
|
||||
sx_row = _sx_header_sx(main_nav)
|
||||
rows = await render_to_sx_with_env("sx-layout-full", {},
|
||||
sx_row=SxExpr(sx_row))
|
||||
sx_row=sx_row)
|
||||
return await oob_header_sx("root-header-child", "sx-header-child", rows)
|
||||
|
||||
|
||||
async def _sx_section_full_headers(ctx: dict, **kw: Any) -> str:
|
||||
"""Full headers for sx section pages: root + sx row + sub row."""
|
||||
from shared.sx.helpers import render_to_sx_with_env
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
section = kw.get("section", "")
|
||||
sub_label = kw.get("sub_label", section)
|
||||
@@ -51,13 +48,12 @@ async def _sx_section_full_headers(ctx: dict, **kw: Any) -> str:
|
||||
sub_row = _sub_row_sx(sub_label, sub_href, sub_nav, selected)
|
||||
sx_row = _sx_header_sx(main_nav, child=sub_row)
|
||||
return await render_to_sx_with_env("sx-section-layout-full", {},
|
||||
sx_row=SxExpr(sx_row))
|
||||
sx_row=sx_row)
|
||||
|
||||
|
||||
async def _sx_section_oob_headers(ctx: dict, **kw: Any) -> str:
|
||||
"""OOB headers for sx section pages."""
|
||||
from shared.sx.helpers import render_to_sx_with_env, oob_header_sx
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
section = kw.get("section", "")
|
||||
sub_label = kw.get("sub_label", section)
|
||||
@@ -69,7 +65,7 @@ async def _sx_section_oob_headers(ctx: dict, **kw: Any) -> str:
|
||||
sub_row = _sub_row_sx(sub_label, sub_href, sub_nav, selected)
|
||||
sx_row = _sx_header_sx(main_nav, child=sub_row)
|
||||
rows = await render_to_sx_with_env("sx-section-layout-full", {},
|
||||
sx_row=SxExpr(sx_row))
|
||||
sx_row=sx_row)
|
||||
return await oob_header_sx("root-header-child", "sx-header-child", rows)
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ def _sx_header_sx(nav: str | None = None, *, child: str | None = None) -> str:
|
||||
return sx_call("menu-row-sx",
|
||||
id="sx-row", level=1, colour="violet",
|
||||
link_href="/", link_label="sx",
|
||||
link_label_content=SxExpr(label_sx),
|
||||
link_label_content=label_sx,
|
||||
nav=SxExpr(nav) if nav else None,
|
||||
child_id="sx-header-child",
|
||||
child=SxExpr(child) if child else None,
|
||||
|
||||
Reference in New Issue
Block a user