Migrate all apps to defpage declarative page routes

Replace Python GET page handlers with declarative defpage definitions in .sx
files across all 8 apps (sx docs, orders, account, market, cart, federation,
events, blog). Each app now has sxc/pages/ with setup functions, layout
registrations, page helpers, and .sx defpage declarations.

Core infrastructure: add g I/O primitive, PageDef support for auth/layout/
data/content/filter/aside/menu slots, post_author auth level, and custom
layout registration. Remove ~1400 lines of render_*_page/render_*_oob
boilerplate. Update all endpoint references in routes, sx_components, and
templates to defpage_* naming.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-03 14:52:34 +00:00
parent 5b4cacaf19
commit c243d17eeb
108 changed files with 3598 additions and 2851 deletions

View File

@@ -12,7 +12,7 @@ from typing import Any
from shared.sx.jinja_bridge import load_service_components
from shared.sx.helpers import (
call_url, sx_call, SxExpr,
root_header_sx, full_page_sx, header_child_sx, oob_page_sx,
root_header_sx, full_page_sx,
)
# Load account-specific .sx components + handlers at import time
@@ -238,88 +238,8 @@ def _device_approved_content() -> str:
# Public API: Account dashboard
# ---------------------------------------------------------------------------
async def render_account_page(ctx: dict) -> str:
"""Full page: account dashboard."""
main = _account_main_panel_sx(ctx)
hdr = root_header_sx(ctx)
hdr_child = header_child_sx(_auth_header_sx(ctx))
header_rows = "(<> " + hdr + " " + hdr_child + ")"
return full_page_sx(ctx, header_rows=header_rows,
content=main,
menu=_auth_nav_mobile_sx(ctx))
async def render_account_oob(ctx: dict) -> str:
"""OOB response for account dashboard."""
main = _account_main_panel_sx(ctx)
oobs = "(<> " + _auth_header_sx(ctx, oob=True) + " " + root_header_sx(ctx, oob=True) + ")"
return oob_page_sx(oobs=oobs,
content=main,
menu=_auth_nav_mobile_sx(ctx))
# ---------------------------------------------------------------------------
# Public API: Newsletters
# ---------------------------------------------------------------------------
async def render_newsletters_page(ctx: dict, newsletter_list: list) -> str:
"""Full page: newsletters."""
main = _newsletters_panel_sx(ctx, newsletter_list)
hdr = root_header_sx(ctx)
hdr_child = header_child_sx(_auth_header_sx(ctx))
header_rows = "(<> " + hdr + " " + hdr_child + ")"
return full_page_sx(ctx, header_rows=header_rows,
content=main,
menu=_auth_nav_mobile_sx(ctx))
async def render_newsletters_oob(ctx: dict, newsletter_list: list) -> str:
"""OOB response for newsletters."""
main = _newsletters_panel_sx(ctx, newsletter_list)
oobs = "(<> " + _auth_header_sx(ctx, oob=True) + " " + root_header_sx(ctx, oob=True) + ")"
return oob_page_sx(oobs=oobs,
content=main,
menu=_auth_nav_mobile_sx(ctx))
# ---------------------------------------------------------------------------
# Public API: Fragment pages
# ---------------------------------------------------------------------------
async def render_fragment_page(ctx: dict, page_fragment: str) -> str:
"""Full page: fragment-provided content.
*page_fragment* may be sx source (from text/sx fragments wrapped in
SxExpr) or HTML (from text/html fragments). Sx source is embedded
directly; HTML is wrapped in ``~rich-text``.
"""
from shared.sx.parser import SxExpr
hdr = root_header_sx(ctx)
hdr_child = header_child_sx(_auth_header_sx(ctx))
header_rows = "(<> " + hdr + " " + hdr_child + ")"
content = _fragment_content(page_fragment)
return full_page_sx(ctx, header_rows=header_rows,
content=content,
menu=_auth_nav_mobile_sx(ctx))
async def render_fragment_oob(ctx: dict, page_fragment: str) -> str:
"""OOB response for fragment pages."""
oobs = "(<> " + _auth_header_sx(ctx, oob=True) + " " + root_header_sx(ctx, oob=True) + ")"
content = _fragment_content(page_fragment)
return oob_page_sx(oobs=oobs,
content=content,
menu=_auth_nav_mobile_sx(ctx))
def _fragment_content(frag: object) -> str: