All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m41s
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>
211 lines
7.3 KiB
Python
211 lines
7.3 KiB
Python
"""SX docs defpage setup — registers layouts and page helpers."""
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
|
|
def setup_sx_pages() -> None:
|
|
"""Register sx-specific layouts, page helpers, and load page definitions.
|
|
|
|
Called during app startup before mount_pages().
|
|
"""
|
|
_register_sx_layouts()
|
|
_register_sx_helpers()
|
|
_load_sx_page_files()
|
|
|
|
|
|
def _load_sx_page_files() -> None:
|
|
"""Load defpage definitions from sx/sxc/pages/*.sx."""
|
|
import os
|
|
from shared.sx.pages import load_page_dir
|
|
pages_dir = os.path.dirname(__file__)
|
|
load_page_dir(pages_dir, "sx")
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Layouts
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def _register_sx_layouts() -> None:
|
|
"""Register the sx docs layout presets."""
|
|
from shared.sx.layouts import register_custom_layout
|
|
|
|
register_custom_layout("sx", _sx_full_headers, _sx_oob_headers, _sx_mobile)
|
|
register_custom_layout("sx-section", _sx_section_full_headers, _sx_section_oob_headers, _sx_section_mobile)
|
|
|
|
|
|
def _sx_full_headers(ctx: dict, **kw: Any) -> str:
|
|
"""Full headers for sx home page: root + sx menu row."""
|
|
from shared.sx.helpers import root_header_sx
|
|
from sxc.sx_components import _sx_header_sx, _main_nav_sx
|
|
|
|
main_nav = _main_nav_sx(kw.get("section"))
|
|
root_hdr = root_header_sx(ctx)
|
|
sx_row = _sx_header_sx(main_nav)
|
|
return "(<> " + root_hdr + " " + sx_row + ")"
|
|
|
|
|
|
def _sx_oob_headers(ctx: dict, **kw: Any) -> str:
|
|
"""OOB headers for sx home page."""
|
|
from shared.sx.helpers import root_header_sx, oob_header_sx
|
|
from sxc.sx_components import _sx_header_sx, _main_nav_sx
|
|
|
|
root_hdr = root_header_sx(ctx)
|
|
main_nav = _main_nav_sx(kw.get("section"))
|
|
sx_row = _sx_header_sx(main_nav)
|
|
rows = "(<> " + root_hdr + " " + sx_row + ")"
|
|
return oob_header_sx("root-header-child", "sx-header-child", rows)
|
|
|
|
|
|
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 root_header_sx
|
|
from sxc.sx_components import (
|
|
_sx_header_sx, _main_nav_sx, _sub_row_sx,
|
|
)
|
|
|
|
section = kw.get("section", "")
|
|
sub_label = kw.get("sub_label", section)
|
|
sub_href = kw.get("sub_href", "/")
|
|
sub_nav = kw.get("sub_nav", "")
|
|
selected = kw.get("selected", "")
|
|
|
|
root_hdr = root_header_sx(ctx)
|
|
main_nav = _main_nav_sx(section)
|
|
sub_row = _sub_row_sx(sub_label, sub_href, sub_nav, selected)
|
|
sx_row = _sx_header_sx(main_nav, child=sub_row)
|
|
return "(<> " + root_hdr + " " + sx_row + ")"
|
|
|
|
|
|
def _sx_section_oob_headers(ctx: dict, **kw: Any) -> str:
|
|
"""OOB headers for sx section pages."""
|
|
from shared.sx.helpers import root_header_sx, oob_header_sx
|
|
from sxc.sx_components import (
|
|
_sx_header_sx, _main_nav_sx, _sub_row_sx,
|
|
)
|
|
|
|
section = kw.get("section", "")
|
|
sub_label = kw.get("sub_label", section)
|
|
sub_href = kw.get("sub_href", "/")
|
|
sub_nav = kw.get("sub_nav", "")
|
|
selected = kw.get("selected", "")
|
|
|
|
root_hdr = root_header_sx(ctx)
|
|
main_nav = _main_nav_sx(section)
|
|
sub_row = _sub_row_sx(sub_label, sub_href, sub_nav, selected)
|
|
sx_row = _sx_header_sx(main_nav, child=sub_row)
|
|
rows = "(<> " + root_hdr + " " + sx_row + ")"
|
|
return oob_header_sx("root-header-child", "sx-header-child", rows)
|
|
|
|
|
|
def _sx_mobile(ctx: dict, **kw: Any) -> str:
|
|
"""Mobile menu for sx home page: main nav + root."""
|
|
from shared.sx.helpers import (
|
|
mobile_menu_sx, mobile_root_nav_sx, sx_call, SxExpr,
|
|
)
|
|
from sxc.sx_components import _main_nav_sx
|
|
|
|
main_nav = _main_nav_sx(kw.get("section"))
|
|
return mobile_menu_sx(
|
|
sx_call("mobile-menu-section",
|
|
label="sx", href="/", level=1, colour="violet",
|
|
items=SxExpr(main_nav)),
|
|
mobile_root_nav_sx(ctx),
|
|
)
|
|
|
|
|
|
def _sx_section_mobile(ctx: dict, **kw: Any) -> str:
|
|
"""Mobile menu for sx section pages: sub nav + main nav + root."""
|
|
from shared.sx.helpers import (
|
|
mobile_menu_sx, mobile_root_nav_sx, sx_call, SxExpr,
|
|
)
|
|
from sxc.sx_components import _main_nav_sx
|
|
|
|
section = kw.get("section", "")
|
|
sub_label = kw.get("sub_label", section)
|
|
sub_href = kw.get("sub_href", "/")
|
|
sub_nav = kw.get("sub_nav", "")
|
|
main_nav = _main_nav_sx(section)
|
|
|
|
parts = []
|
|
if sub_nav:
|
|
parts.append(sx_call("mobile-menu-section",
|
|
label=sub_label, href=sub_href, level=2, colour="violet",
|
|
items=SxExpr(sub_nav)))
|
|
parts.append(sx_call("mobile-menu-section",
|
|
label="sx", href="/", level=1, colour="violet",
|
|
items=SxExpr(main_nav)))
|
|
parts.append(mobile_root_nav_sx(ctx))
|
|
return mobile_menu_sx(*parts)
|
|
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Page helpers — Python functions callable from defpage content expressions
|
|
# ---------------------------------------------------------------------------
|
|
|
|
def _register_sx_helpers() -> None:
|
|
"""Register Python content builder functions as page helpers."""
|
|
from shared.sx.pages import register_page_helpers
|
|
from sxc.sx_components import (
|
|
_docs_content_sx, _reference_content_sx,
|
|
_protocol_content_sx, _examples_content_sx,
|
|
_essay_content_sx,
|
|
_docs_nav_sx, _reference_nav_sx,
|
|
_protocols_nav_sx, _examples_nav_sx, _essays_nav_sx,
|
|
)
|
|
from content.highlight import highlight as _highlight
|
|
from content.pages import (
|
|
DOCS_NAV, REFERENCE_NAV, PROTOCOLS_NAV,
|
|
EXAMPLES_NAV, ESSAYS_NAV,
|
|
)
|
|
|
|
def _find_current(nav_list, slug, match_fn=None):
|
|
"""Find the current nav label for a slug."""
|
|
if match_fn:
|
|
return match_fn(nav_list, slug)
|
|
for label, href in nav_list:
|
|
if href.endswith(slug):
|
|
return label
|
|
return None
|
|
|
|
def _home_content():
|
|
"""Build home page content (uses highlight for hero code block)."""
|
|
hero_code = _highlight(
|
|
'(div :class "p-4 bg-white rounded shadow"\n'
|
|
' (h1 :class "text-2xl font-bold" "Hello")\n'
|
|
' (button :sx-get "/api/data"\n'
|
|
' :sx-target "#result"\n'
|
|
' "Load data"))', "lisp")
|
|
return (
|
|
f'(div :id "main-content"'
|
|
f' (~sx-hero {hero_code})'
|
|
f' (~sx-philosophy)'
|
|
f' (~sx-how-it-works)'
|
|
f' (~sx-credits))'
|
|
)
|
|
|
|
register_page_helpers("sx", {
|
|
# Content builders
|
|
"home-content": _home_content,
|
|
"docs-content": _docs_content_sx,
|
|
"reference-content": _reference_content_sx,
|
|
"protocol-content": _protocol_content_sx,
|
|
"examples-content": _examples_content_sx,
|
|
"essay-content": _essay_content_sx,
|
|
"highlight": _highlight,
|
|
# Nav builders
|
|
"docs-nav": _docs_nav_sx,
|
|
"reference-nav": _reference_nav_sx,
|
|
"protocols-nav": _protocols_nav_sx,
|
|
"examples-nav": _examples_nav_sx,
|
|
"essays-nav": _essays_nav_sx,
|
|
# Nav data (for current label lookup)
|
|
"DOCS_NAV": DOCS_NAV,
|
|
"REFERENCE_NAV": REFERENCE_NAV,
|
|
"PROTOCOLS_NAV": PROTOCOLS_NAV,
|
|
"EXAMPLES_NAV": EXAMPLES_NAV,
|
|
"ESSAYS_NAV": ESSAYS_NAV,
|
|
# Utility
|
|
"find-current": _find_current,
|
|
})
|