Merge branch 'worktree-macros-essays' into macros

This commit is contained in:
2026-03-04 17:13:50 +00:00
18 changed files with 446 additions and 168 deletions

View File

@@ -125,7 +125,7 @@ def register() -> Blueprint:
if ident["session_id"] is not None: if ident["session_id"] is not None:
frag_params["session_id"] = ident["session_id"] frag_params["session_id"] = ident["session_id"]
from sxc.pages.renders import render_ticket_widget from sxc.pages.tickets import render_ticket_widget
widget_html = await render_ticket_widget(entry, qty, "/all-tickets/adjust") widget_html = await render_ticket_widget(entry, qty, "/all-tickets/adjust")
mini_html = await fetch_fragment("cart", "cart-mini", params=frag_params, required=False) mini_html = await fetch_fragment("cart", "cart-mini", params=frag_params, required=False)
return sx_response(widget_html + (mini_html or "")) return sx_response(widget_html + (mini_html or ""))

View File

@@ -224,7 +224,7 @@ def register():
if post_data: if post_data:
from shared.services.entry_associations import get_associated_entries from shared.services.entry_associations import get_associated_entries
from sxc.pages.renders import render_post_nav_entries_oob from sxc.pages.entries import render_post_nav_entries_oob
post_id = (post_data.get("post") or {}).get("id") post_id = (post_data.get("post") or {}).get("id")
cals = ( cals = (

View File

@@ -279,12 +279,12 @@ def register():
result = await g.s.execute(stmt) result = await g.s.execute(stmt)
day_slots = list(result.scalars()) day_slots = list(result.scalars())
from sxc.pages.renders import render_entry_add_form from sxc.pages.entries import render_entry_add_form
return sx_response(await render_entry_add_form(g.calendar, day, month, year, day_slots)) return sx_response(await render_entry_add_form(g.calendar, day, month, year, day_slots))
@bp.get("/add-button/") @bp.get("/add-button/")
async def add_button(day: int, month: int, year: int, **kwargs): async def add_button(day: int, month: int, year: int, **kwargs):
from sxc.pages.renders import render_entry_add_button from sxc.pages.entries import render_entry_add_button
return sx_response(await render_entry_add_button(g.calendar, day, month, year)) return sx_response(await render_entry_add_button(g.calendar, day, month, year))

View File

@@ -111,7 +111,7 @@ def register():
) )
# Render OOB nav # Render OOB nav
from sxc.pages.renders import render_day_entries_nav_oob from sxc.pages.entries import render_day_entries_nav_oob
return await render_day_entries_nav_oob(visible.confirmed_entries, calendar, day_date) return await render_day_entries_nav_oob(visible.confirmed_entries, calendar, day_date)
async def get_post_nav_oob(entry_id: int): async def get_post_nav_oob(entry_id: int):
@@ -148,7 +148,7 @@ def register():
).scalars().all() ).scalars().all()
# Render OOB nav for this post # Render OOB nav for this post
from sxc.pages.renders import render_post_nav_entries_oob from sxc.pages.entries import render_post_nav_entries_oob
nav_oob = await render_post_nav_entries_oob(associated_entries, calendars, post) nav_oob = await render_post_nav_entries_oob(associated_entries, calendars, post)
nav_oobs.append(nav_oob) nav_oobs.append(nav_oob)
@@ -256,7 +256,7 @@ def register():
result = await g.s.execute(stmt) result = await g.s.execute(stmt)
day_slots = list(result.scalars()) day_slots = list(result.scalars())
from sxc.pages.renders import render_entry_edit_form from sxc.pages.entries import render_entry_edit_form
return sx_response(await render_entry_edit_form(g.entry, g.calendar, day, month, year, day_slots)) return sx_response(await render_entry_edit_form(g.entry, g.calendar, day, month, year, day_slots))
@bp.put("/") @bp.put("/")
@@ -448,7 +448,7 @@ def register():
# Re-read entry to get updated state # Re-read entry to get updated state
await g.s.refresh(g.entry) await g.s.refresh(g.entry)
from sxc.pages.renders import render_entry_optioned from sxc.pages.entries import render_entry_optioned
html = await render_entry_optioned(g.entry, g.calendar, day, month, year) html = await render_entry_optioned(g.entry, g.calendar, day, month, year)
return sx_response(html + day_nav_oob + post_nav_oob) return sx_response(html + day_nav_oob + post_nav_oob)
@@ -473,7 +473,7 @@ def register():
# Re-read entry to get updated state # Re-read entry to get updated state
await g.s.refresh(g.entry) await g.s.refresh(g.entry)
from sxc.pages.renders import render_entry_optioned from sxc.pages.entries import render_entry_optioned
html = await render_entry_optioned(g.entry, g.calendar, day, month, year) html = await render_entry_optioned(g.entry, g.calendar, day, month, year)
return sx_response(html + day_nav_oob + post_nav_oob) return sx_response(html + day_nav_oob + post_nav_oob)
@@ -498,7 +498,7 @@ def register():
# Re-read entry to get updated state # Re-read entry to get updated state
await g.s.refresh(g.entry) await g.s.refresh(g.entry)
from sxc.pages.renders import render_entry_optioned from sxc.pages.entries import render_entry_optioned
html = await render_entry_optioned(g.entry, g.calendar, day, month, year) html = await render_entry_optioned(g.entry, g.calendar, day, month, year)
return sx_response(html + day_nav_oob + post_nav_oob) return sx_response(html + day_nav_oob + post_nav_oob)
@@ -542,7 +542,7 @@ def register():
# Return just the tickets fragment (targeted by hx-target="#entry-tickets-...") # Return just the tickets fragment (targeted by hx-target="#entry-tickets-...")
await g.s.refresh(g.entry) await g.s.refresh(g.entry)
from sxc.pages.renders import render_entry_tickets_config from sxc.pages.entries import render_entry_tickets_config
html = await render_entry_tickets_config(g.entry, g.calendar, request.view_args.get("day"), request.view_args.get("month"), request.view_args.get("year")) html = await render_entry_tickets_config(g.entry, g.calendar, request.view_args.get("day"), request.view_args.get("month"), request.view_args.get("year"))
return sx_response(html) return sx_response(html)
@@ -558,7 +558,7 @@ def register():
total_pages = math.ceil(total / per_page) if total > 0 else 0 total_pages = math.ceil(total / per_page) if total > 0 else 0
va = request.view_args or {} va = request.view_args or {}
from sxc.pages.renders import render_post_search_results from sxc.pages.entries import render_post_search_results
return sx_response(await render_post_search_results( return sx_response(await render_post_search_results(
search_posts, query, page, total_pages, search_posts, query, page, total_pages,
g.entry, g.calendar, g.entry, g.calendar,
@@ -592,7 +592,7 @@ def register():
entry_posts = await get_entry_posts(g.s, entry_id) entry_posts = await get_entry_posts(g.s, entry_id)
# Return updated posts list + OOB nav update # Return updated posts list + OOB nav update
from sxc.pages.renders import render_entry_posts_panel, render_entry_posts_nav_oob from sxc.pages.entries import render_entry_posts_panel, render_entry_posts_nav_oob
va = request.view_args or {} va = request.view_args or {}
html = await render_entry_posts_panel(entry_posts, g.entry, g.calendar, va.get("day"), va.get("month"), va.get("year")) html = await render_entry_posts_panel(entry_posts, g.entry, g.calendar, va.get("day"), va.get("month"), va.get("year"))
nav_oob = await render_entry_posts_nav_oob(entry_posts) nav_oob = await render_entry_posts_nav_oob(entry_posts)
@@ -614,7 +614,7 @@ def register():
entry_posts = await get_entry_posts(g.s, entry_id) entry_posts = await get_entry_posts(g.s, entry_id)
# Return updated posts list + OOB nav update # Return updated posts list + OOB nav update
from sxc.pages.renders import render_entry_posts_panel, render_entry_posts_nav_oob from sxc.pages.entries import render_entry_posts_panel, render_entry_posts_nav_oob
va = request.view_args or {} va = request.view_args or {}
html = await render_entry_posts_panel(entry_posts, g.entry, g.calendar, va.get("day"), va.get("month"), va.get("year")) html = await render_entry_posts_panel(entry_posts, g.entry, g.calendar, va.get("day"), va.get("month"), va.get("year"))
nav_oob = await render_entry_posts_nav_oob(entry_posts) nav_oob = await render_entry_posts_nav_oob(entry_posts)

View File

@@ -74,7 +74,7 @@ def register():
# Blog-embedded mode: also update post nav # Blog-embedded mode: also update post nav
if post_data: if post_data:
from shared.services.entry_associations import get_associated_entries from shared.services.entry_associations import get_associated_entries
from sxc.pages.renders import render_post_nav_entries_oob from sxc.pages.entries import render_post_nav_entries_oob
cals = ( cals = (
await g.s.execute( await g.s.execute(

View File

@@ -106,7 +106,7 @@ def register() -> Blueprint:
if ident["session_id"] is not None: if ident["session_id"] is not None:
frag_params["session_id"] = ident["session_id"] frag_params["session_id"] = ident["session_id"]
from sxc.pages.renders import render_ticket_widget from sxc.pages.tickets import render_ticket_widget
widget_html = await render_ticket_widget(entry, qty, f"/{g.post_slug}/tickets/adjust") widget_html = await render_ticket_widget(entry, qty, f"/{g.post_slug}/tickets/adjust")
mini_html = await fetch_fragment("cart", "cart-mini", params=frag_params, required=False) mini_html = await fetch_fragment("cart", "cart-mini", params=frag_params, required=False)
return sx_response(widget_html + (mini_html or "")) return sx_response(widget_html + (mini_html or ""))

View File

@@ -35,7 +35,7 @@ def register():
slot = await svc_get_slot(g.s, slot_id) slot = await svc_get_slot(g.s, slot_id)
if not slot: if not slot:
return await make_response("Not found", 404) return await make_response("Not found", 404)
from sxc.pages.renders import render_slot_edit_form from sxc.pages.slots import render_slot_edit_form
return sx_response(await render_slot_edit_form(slot, g.calendar)) return sx_response(await render_slot_edit_form(slot, g.calendar))
@bp.get("/view/") @bp.get("/view/")
@@ -44,7 +44,7 @@ def register():
slot = await svc_get_slot(g.s, slot_id) slot = await svc_get_slot(g.s, slot_id)
if not slot: if not slot:
return await make_response("Not found", 404) return await make_response("Not found", 404)
from sxc.pages.renders import render_slot_main_panel from sxc.pages.slots import render_slot_main_panel
return sx_response(await render_slot_main_panel(slot, g.calendar)) return sx_response(await render_slot_main_panel(slot, g.calendar))
@bp.delete("/") @bp.delete("/")
@@ -53,7 +53,7 @@ def register():
async def slot_delete(slot_id: int, **kwargs): async def slot_delete(slot_id: int, **kwargs):
await svc_delete_slot(g.s, slot_id) await svc_delete_slot(g.s, slot_id)
slots = await svc_list_slots(g.s, g.calendar.id) slots = await svc_list_slots(g.s, g.calendar.id)
from sxc.pages.renders import render_slots_table from sxc.pages.slots import render_slots_table
return sx_response(await render_slots_table(slots, g.calendar)) return sx_response(await render_slots_table(slots, g.calendar))
@bp.put("/") @bp.put("/")
@@ -135,7 +135,7 @@ def register():
} }
), 422 ), 422
from sxc.pages.renders import render_slot_main_panel from sxc.pages.slots import render_slot_main_panel
return sx_response(await render_slot_main_panel(slot, g.calendar, oob=True)) return sx_response(await render_slot_main_panel(slot, g.calendar, oob=True))

View File

@@ -110,20 +110,20 @@ def register():
# Success → re-render the slots table # Success → re-render the slots table
slots = await svc_list_slots(g.s, g.calendar.id) slots = await svc_list_slots(g.s, g.calendar.id)
from sxc.pages.renders import render_slots_table from sxc.pages.slots import render_slots_table
return sx_response(await render_slots_table(slots, g.calendar)) return sx_response(await render_slots_table(slots, g.calendar))
@bp.get("/add") @bp.get("/add")
@require_admin @require_admin
async def add_form(**kwargs): async def add_form(**kwargs):
from sxc.pages.renders import render_slot_add_form from sxc.pages.slots import render_slot_add_form
return sx_response(await render_slot_add_form(g.calendar)) return sx_response(await render_slot_add_form(g.calendar))
@bp.get("/add-button") @bp.get("/add-button")
@require_admin @require_admin
async def add_button(**kwargs): async def add_button(**kwargs):
from sxc.pages.renders import render_slot_add_button from sxc.pages.slots import render_slot_add_button
return sx_response(await render_slot_add_button(g.calendar)) return sx_response(await render_slot_add_button(g.calendar))
return bp return bp

View File

@@ -53,7 +53,7 @@ def register() -> Blueprint:
tickets = await get_tickets_for_entry(g.s, entry_id) tickets = await get_tickets_for_entry(g.s, entry_id)
from sxc.pages.renders import render_entry_tickets_admin from sxc.pages.tickets import render_entry_tickets_admin
html = await render_entry_tickets_admin(entry, tickets) html = await render_entry_tickets_admin(entry, tickets)
return sx_response(html) return sx_response(html)
@@ -69,7 +69,7 @@ def register() -> Blueprint:
) )
ticket = await get_ticket_by_code(g.s, code) ticket = await get_ticket_by_code(g.s, code)
from sxc.pages.renders import render_lookup_result from sxc.pages.tickets import render_lookup_result
if not ticket: if not ticket:
return sx_response(await render_lookup_result(None, "Ticket not found")) return sx_response(await render_lookup_result(None, "Ticket not found"))
@@ -82,7 +82,7 @@ def register() -> Blueprint:
"""Check in a ticket by its code.""" """Check in a ticket by its code."""
success, error = await checkin_ticket(g.s, code) success, error = await checkin_ticket(g.s, code)
from sxc.pages.renders import render_checkin_result from sxc.pages.tickets import render_checkin_result
if not success: if not success:
return sx_response(await render_checkin_result(False, error, None)) return sx_response(await render_checkin_result(False, error, None))

View File

@@ -30,7 +30,7 @@ def register():
if not ticket_type: if not ticket_type:
return await make_response("Not found", 404) return await make_response("Not found", 404)
from sxc.pages.renders import render_ticket_type_edit_form from sxc.pages.tickets import render_ticket_type_edit_form
va = request.view_args or {} va = request.view_args or {}
return sx_response(await render_ticket_type_edit_form( return sx_response(await render_ticket_type_edit_form(
ticket_type, g.entry, g.calendar, ticket_type, g.entry, g.calendar,
@@ -45,7 +45,7 @@ def register():
if not ticket_type: if not ticket_type:
return await make_response("Not found", 404) return await make_response("Not found", 404)
from sxc.pages.renders import render_ticket_type_main_panel from sxc.pages.tickets import render_ticket_type_main_panel
va = request.view_args or {} va = request.view_args or {}
return sx_response(await render_ticket_type_main_panel( return sx_response(await render_ticket_type_main_panel(
ticket_type, g.entry, g.calendar, ticket_type, g.entry, g.calendar,
@@ -112,7 +112,7 @@ def register():
return await make_response("Not found", 404) return await make_response("Not found", 404)
# Return updated view with OOB flag # Return updated view with OOB flag
from sxc.pages.renders import render_ticket_type_main_panel from sxc.pages.tickets import render_ticket_type_main_panel
va = request.view_args or {} va = request.view_args or {}
return sx_response(await render_ticket_type_main_panel( return sx_response(await render_ticket_type_main_panel(
ticket_type, g.entry, g.calendar, ticket_type, g.entry, g.calendar,
@@ -131,7 +131,7 @@ def register():
# Re-render the ticket types list # Re-render the ticket types list
ticket_types = await svc_list_ticket_types(g.s, g.entry.id) ticket_types = await svc_list_ticket_types(g.s, g.entry.id)
from sxc.pages.renders import render_ticket_types_table from sxc.pages.tickets import render_ticket_types_table
va = request.view_args or {} va = request.view_args or {}
return sx_response(await render_ticket_types_table( return sx_response(await render_ticket_types_table(
ticket_types, g.entry, g.calendar, ticket_types, g.entry, g.calendar,

View File

@@ -93,7 +93,7 @@ def register():
# Success → re-render the ticket types table # Success → re-render the ticket types table
ticket_types = await svc_list_ticket_types(g.s, g.entry.id) ticket_types = await svc_list_ticket_types(g.s, g.entry.id)
from sxc.pages.renders import render_ticket_types_table from sxc.pages.tickets import render_ticket_types_table
va = request.view_args or {} va = request.view_args or {}
return sx_response(await render_ticket_types_table( return sx_response(await render_ticket_types_table(
ticket_types, g.entry, g.calendar, ticket_types, g.entry, g.calendar,
@@ -104,7 +104,7 @@ def register():
@require_admin @require_admin
async def add_form(**kwargs): async def add_form(**kwargs):
"""Show the add ticket type form.""" """Show the add ticket type form."""
from sxc.pages.renders import render_ticket_type_add_form from sxc.pages.tickets import render_ticket_type_add_form
va = request.view_args or {} va = request.view_args or {}
return sx_response(await render_ticket_type_add_form( return sx_response(await render_ticket_type_add_form(
g.entry, g.calendar, g.entry, g.calendar,
@@ -115,7 +115,7 @@ def register():
@require_admin @require_admin
async def add_button(**kwargs): async def add_button(**kwargs):
"""Show the add ticket type button.""" """Show the add ticket type button."""
from sxc.pages.renders import render_ticket_type_add_button from sxc.pages.tickets import render_ticket_type_add_button
va = request.view_args or {} va = request.view_args or {}
return sx_response(await render_ticket_type_add_button( return sx_response(await render_ticket_type_add_button(
g.entry, g.calendar, g.entry, g.calendar,

View File

@@ -126,7 +126,7 @@ def register() -> Blueprint:
summary = dto_from_dict(CartSummaryDTO, raw_summary) if raw_summary else CartSummaryDTO() summary = dto_from_dict(CartSummaryDTO, raw_summary) if raw_summary else CartSummaryDTO()
cart_count = summary.count + summary.calendar_count + summary.ticket_count cart_count = summary.count + summary.calendar_count + summary.ticket_count
from sxc.pages.renders import render_buy_result from sxc.pages.tickets import render_buy_result
return sx_response(await render_buy_result(entry, created, remaining, cart_count)) return sx_response(await render_buy_result(entry, created, remaining, cart_count))
@bp.post("/adjust/") @bp.post("/adjust/")
@@ -249,7 +249,7 @@ def register() -> Blueprint:
summary = dto_from_dict(CartSummaryDTO, raw_summary) if raw_summary else CartSummaryDTO() summary = dto_from_dict(CartSummaryDTO, raw_summary) if raw_summary else CartSummaryDTO()
cart_count = summary.count + summary.calendar_count + summary.ticket_count cart_count = summary.count + summary.calendar_count + summary.ticket_count
from sxc.pages.renders import render_adjust_response from sxc.pages.tickets import render_adjust_response
return sx_response(await render_adjust_response( return sx_response(await render_adjust_response(
entry, ticket_remaining, ticket_sold_count, entry, ticket_remaining, ticket_sold_count,
user_ticket_count, user_ticket_counts_by_type, cart_count, user_ticket_count, user_ticket_counts_by_type, cart_count,

View File

@@ -4,8 +4,7 @@ from __future__ import annotations
def setup_events_pages() -> None: def setup_events_pages() -> None:
"""Register events-specific layouts, page helpers, and load page definitions.""" """Register events-specific layouts, page helpers, and load page definitions."""
from .layouts import _register_events_layouts from .helpers import _register_events_layouts, _register_events_helpers
from .helpers import _register_events_helpers
_register_events_layouts() _register_events_layouts()
_register_events_helpers() _register_events_helpers()
_load_events_page_files() _load_events_page_files()
@@ -15,7 +14,7 @@ def _load_events_page_files() -> None:
import os import os
from shared.sx.pages import load_page_dir from shared.sx.pages import load_page_dir
from shared.sx.jinja_bridge import load_service_components from shared.sx.jinja_bridge import load_service_components
sxc_dir = os.path.dirname(os.path.dirname(__file__)) sxc_dir = os.path.dirname(os.path.dirname(__file__)) # events/sxc/
service_root = os.path.dirname(sxc_dir) service_root = os.path.dirname(sxc_dir) # events/
load_service_components(service_root, service_name="events") load_service_components(service_root, service_name="events")
load_page_dir(os.path.dirname(__file__), "events") load_page_dir(os.path.dirname(__file__), "events")

View File

@@ -210,7 +210,7 @@ async def _entry_main_panel_html(ctx: dict) -> str:
"""Render the entry detail panel (name, slot, time, state, cost, tickets, """Render the entry detail panel (name, slot, time, state, cost, tickets,
buy form, date, posts, options + edit button).""" buy form, date, posts, options + edit button)."""
from quart import url_for from quart import url_for
from .tickets import render_buy_form, render_entry_tickets_config from .tickets import render_buy_form
entry = ctx.get("entry") entry = ctx.get("entry")
if not entry: if not entry:

View File

@@ -1,8 +1,35 @@
"""Page helpers — _h_* helper functions + _register_events_helpers + _ensure_* context hydration.""" """Layout registrations, page helpers, and shared hydration helpers."""
from __future__ import annotations from __future__ import annotations
from typing import Any from typing import Any
from shared.sx.helpers import render_to_sx
from .utils import _clear_deeper_oob, _ensure_container_nav
from .calendar import (
_post_header_sx, _calendar_header_sx,
_calendar_admin_header_sx, _day_header_sx,
_day_admin_header_sx, _markets_header_sx,
_calendars_main_panel_sx,
_calendar_admin_main_panel_html,
_day_admin_main_panel_html,
_markets_main_panel_html,
)
from .entries import (
_entry_header_html, _entry_main_panel_html,
_entry_nav_html,
_entry_admin_header_html, _entry_admin_main_panel_html,
)
from .tickets import (
_tickets_main_panel_html, _ticket_detail_panel_html,
_ticket_admin_main_panel_html,
_ticket_types_header_html, _ticket_type_header_html,
render_ticket_type_main_panel, render_ticket_types_table,
)
from .slots import (
_slot_header_html, render_slot_main_panel, render_slots_table,
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Shared hydration helpers # Shared hydration helpers
@@ -181,6 +208,279 @@ async def _ensure_day_data(year: int, month: int, day: int) -> None:
) )
# ---------------------------------------------------------------------------
# Layouts
# ---------------------------------------------------------------------------
def _register_events_layouts() -> None:
from shared.sx.layouts import register_custom_layout
register_custom_layout("events-calendar-admin", _cal_admin_full, _cal_admin_oob)
register_custom_layout("events-slots", _slots_full, _slots_oob)
register_custom_layout("events-slot", _slot_full, _slot_oob)
register_custom_layout("events-day-admin", _day_admin_full, _day_admin_oob)
register_custom_layout("events-entry", _entry_full, _entry_oob)
register_custom_layout("events-entry-admin", _entry_admin_full, _entry_admin_oob)
register_custom_layout("events-ticket-types", _ticket_types_full, _ticket_types_oob)
register_custom_layout("events-ticket-type", _ticket_type_full, _ticket_type_oob)
register_custom_layout("events-markets", _markets_full, _markets_oob)
# --- Calendar admin layout (root + post + child(post-admin + calendar + cal-admin)) ---
async def _cal_admin_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav(ctx)
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-cal-admin-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
admin_header=SxExpr(await post_admin_header_sx(ctx, slug, selected="calendars")),
calendar_header=SxExpr(await _calendar_header_sx(ctx)),
calendar_admin_header=SxExpr(await _calendar_admin_header_sx(ctx)),
)
async def _cal_admin_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx, oob_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav(ctx)
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-cal-admin-layout-oob", _ctx_to_env(ctx, oob=True),
admin_oob=SxExpr(await post_admin_header_sx(ctx, slug, oob=True, selected="calendars")),
cal_oob=SxExpr(await _calendar_header_sx(ctx, oob=True)),
cal_admin_oob_wrap=SxExpr(await oob_header_sx("calendar-header-child",
"calendar-admin-header-child", await _calendar_admin_header_sx(ctx))),
clear_oob=SxExpr(_clear_deeper_oob("post-row", "post-header-child",
"post-admin-row", "post-admin-header-child",
"calendar-row", "calendar-header-child",
"calendar-admin-row", "calendar-admin-header-child")),
)
# --- Slots layout (same full as cal-admin but different OOB) ---
async def _slots_full(ctx: dict, **kw: Any) -> str:
return await _cal_admin_full({**ctx, "is_admin_section": True}, **kw)
async def _slots_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav({**ctx, "is_admin_section": True})
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-slots-layout-oob", _ctx_to_env(ctx, oob=True),
admin_oob=SxExpr(await post_admin_header_sx(ctx, slug, oob=True, selected="calendars")),
cal_admin_oob=SxExpr(await _calendar_admin_header_sx(ctx, oob=True)),
clear_oob=SxExpr(_clear_deeper_oob("post-row", "post-header-child",
"post-admin-row", "post-admin-header-child",
"calendar-row", "calendar-header-child",
"calendar-admin-row", "calendar-admin-header-child")),
)
# --- Slot detail layout (extends cal-admin with slot header) ---
async def _slot_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav({**ctx, "is_admin_section": True})
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-slot-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
admin_header=SxExpr(await post_admin_header_sx(ctx, slug, selected="calendars")),
calendar_header=SxExpr(await _calendar_header_sx(ctx)),
calendar_admin_header=SxExpr(await _calendar_admin_header_sx(ctx)),
slot_header=SxExpr(await _slot_header_html(ctx)),
)
async def _slot_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx, oob_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav({**ctx, "is_admin_section": True})
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-slot-layout-oob", _ctx_to_env(ctx, oob=True),
admin_oob=SxExpr(await post_admin_header_sx(ctx, slug, oob=True, selected="calendars")),
cal_admin_oob=SxExpr(await _calendar_admin_header_sx(ctx, oob=True)),
slot_oob_wrap=SxExpr(await oob_header_sx("calendar-admin-header-child",
"slot-header-child", await _slot_header_html(ctx))),
clear_oob=SxExpr(_clear_deeper_oob("post-row", "post-header-child",
"post-admin-row", "post-admin-header-child",
"calendar-row", "calendar-header-child",
"calendar-admin-row", "calendar-admin-header-child",
"slot-row", "slot-header-child")),
)
# --- Day admin layout (root + post + post-admin + child(cal + day + day-admin)) ---
async def _day_admin_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav(ctx)
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-day-admin-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
admin_header=SxExpr(await post_admin_header_sx(ctx, slug, selected="calendars")),
calendar_header=SxExpr(await _calendar_header_sx(ctx)),
day_header=SxExpr(await _day_header_sx(ctx)),
day_admin_header=SxExpr(await _day_admin_header_sx(ctx)),
)
async def _day_admin_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx, oob_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav(ctx)
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-day-admin-layout-oob", _ctx_to_env(ctx, oob=True),
admin_oob=SxExpr(await post_admin_header_sx(ctx, slug, oob=True, selected="calendars")),
cal_oob=SxExpr(await _calendar_header_sx(ctx, oob=True)),
day_admin_oob_wrap=SxExpr(await oob_header_sx("day-header-child",
"day-admin-header-child", await _day_admin_header_sx(ctx))),
clear_oob=SxExpr(_clear_deeper_oob("post-row", "post-header-child",
"post-admin-row", "post-admin-header-child",
"calendar-row", "calendar-header-child",
"day-row", "day-header-child",
"day-admin-row", "day-admin-header-child")),
)
# --- Entry layout (root + child(post + cal + day + entry), + menu) ---
async def _entry_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-entry-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
calendar_header=SxExpr(await _calendar_header_sx(ctx)),
day_header=SxExpr(await _day_header_sx(ctx)),
entry_header=SxExpr(await _entry_header_html(ctx)),
)
async def _entry_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, oob_header_sx
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-entry-layout-oob", _ctx_to_env(ctx, oob=True),
day_oob=SxExpr(await _day_header_sx(ctx, oob=True)),
entry_oob_wrap=SxExpr(await oob_header_sx("day-header-child",
"entry-header-child", await _entry_header_html(ctx))),
clear_oob=SxExpr(_clear_deeper_oob("post-row", "post-header-child",
"calendar-row", "calendar-header-child",
"day-row", "day-header-child",
"entry-row", "entry-header-child")),
)
# --- Entry admin layout (root + post + child(post-admin + cal + day + entry + entry-admin), + menu) ---
async def _entry_admin_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav(ctx)
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-entry-admin-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
admin_header=SxExpr(await post_admin_header_sx(ctx, slug, selected="calendars")),
calendar_header=SxExpr(await _calendar_header_sx(ctx)),
day_header=SxExpr(await _day_header_sx(ctx)),
entry_header=SxExpr(await _entry_header_html(ctx)),
entry_admin_header=SxExpr(await _entry_admin_header_html(ctx)),
)
async def _entry_admin_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, post_admin_header_sx, oob_header_sx
from shared.sx.parser import SxExpr
ctx = await _ensure_container_nav(ctx)
slug = (ctx.get("post") or {}).get("slug", "")
return await render_to_sx_with_env("events-entry-admin-layout-oob", _ctx_to_env(ctx, oob=True),
admin_oob=SxExpr(await post_admin_header_sx(ctx, slug, oob=True, selected="calendars")),
entry_oob=SxExpr(await _entry_header_html(ctx, oob=True)),
entry_admin_oob_wrap=SxExpr(await oob_header_sx("entry-header-child",
"entry-admin-header-child", await _entry_admin_header_html(ctx))),
clear_oob=SxExpr(_clear_deeper_oob("post-row", "post-header-child",
"post-admin-row", "post-admin-header-child",
"calendar-row", "calendar-header-child",
"day-row", "day-header-child",
"entry-row", "entry-header-child",
"entry-admin-row", "entry-admin-header-child")),
)
# --- Ticket types layout (extends entry admin with ticket-types header, + menu) ---
async def _ticket_types_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-ticket-types-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
calendar_header=SxExpr(await _calendar_header_sx(ctx)),
day_header=SxExpr(await _day_header_sx(ctx)),
entry_header=SxExpr(await _entry_header_html(ctx)),
entry_admin_header=SxExpr(await _entry_admin_header_html(ctx)),
ticket_types_header=SxExpr(await _ticket_types_header_html(ctx)),
)
async def _ticket_types_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, oob_header_sx
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-ticket-types-layout-oob", _ctx_to_env(ctx, oob=True),
entry_admin_oob=SxExpr(await _entry_admin_header_html(ctx, oob=True)),
ticket_types_oob_wrap=SxExpr(await oob_header_sx("entry-admin-header-child",
"ticket_types-header-child", await _ticket_types_header_html(ctx))),
)
# --- Ticket type detail layout (extends ticket types with ticket-type header, + menu) ---
async def _ticket_type_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-ticket-type-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
calendar_header=SxExpr(await _calendar_header_sx(ctx)),
day_header=SxExpr(await _day_header_sx(ctx)),
entry_header=SxExpr(await _entry_header_html(ctx)),
entry_admin_header=SxExpr(await _entry_admin_header_html(ctx)),
ticket_types_header=SxExpr(await _ticket_types_header_html(ctx)),
ticket_type_header=SxExpr(await _ticket_type_header_html(ctx)),
)
async def _ticket_type_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, oob_header_sx
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-ticket-type-layout-oob", _ctx_to_env(ctx, oob=True),
ticket_types_oob=SxExpr(await _ticket_types_header_html(ctx, oob=True)),
ticket_type_oob_wrap=SxExpr(await oob_header_sx("ticket_types-header-child",
"ticket_type-header-child", await _ticket_type_header_html(ctx))),
)
# --- Markets layout (root + child(post + markets)) ---
async def _markets_full(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-markets-layout-full", _ctx_to_env(ctx),
post_header=SxExpr(await _post_header_sx(ctx)),
markets_header=SxExpr(await _markets_header_sx(ctx)),
)
async def _markets_oob(ctx: dict, **kw: Any) -> str:
from shared.sx.helpers import render_to_sx_with_env, _ctx_to_env, oob_header_sx
from shared.sx.parser import SxExpr
return await render_to_sx_with_env("events-markets-layout-oob", _ctx_to_env(ctx, oob=True),
post_oob=SxExpr(await _post_header_sx(ctx, oob=True)),
markets_oob_wrap=SxExpr(await oob_header_sx("post-header-child",
"markets-header-child", await _markets_header_sx(ctx))),
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Page helpers # Page helpers
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@@ -209,7 +509,6 @@ def _register_events_helpers() -> None:
async def _h_calendar_admin_content(calendar_slug=None, **kw): async def _h_calendar_admin_content(calendar_slug=None, **kw):
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
from shared.sx.page import get_template_context from shared.sx.page import get_template_context
from .calendar import _calendar_admin_main_panel_html
ctx = await get_template_context() ctx = await get_template_context()
return await _calendar_admin_main_panel_html(ctx) return await _calendar_admin_main_panel_html(ctx)
@@ -218,7 +517,6 @@ async def _h_day_admin_content(calendar_slug=None, year=None, month=None, day=No
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
if year is not None: if year is not None:
await _ensure_day_data(int(year), int(month), int(day)) await _ensure_day_data(int(year), int(month), int(day))
from .calendar import _day_admin_main_panel_html
return await _day_admin_main_panel_html({}) return await _day_admin_main_panel_html({})
@@ -227,7 +525,6 @@ async def _h_slots_content(calendar_slug=None, **kw):
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
calendar = getattr(g, "calendar", None) calendar = getattr(g, "calendar", None)
from bp.slots.services.slots import list_slots as svc_list_slots from bp.slots.services.slots import list_slots as svc_list_slots
from .slots import render_slots_table
slots = await svc_list_slots(g.s, calendar.id) if calendar else [] slots = await svc_list_slots(g.s, calendar.id) if calendar else []
_add_to_defpage_ctx(slots=slots) _add_to_defpage_ctx(slots=slots)
return await render_slots_table(slots, calendar) return await render_slots_table(slots, calendar)
@@ -237,7 +534,6 @@ async def _h_slot_content(calendar_slug=None, slot_id=None, **kw):
from quart import g, abort from quart import g, abort
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
from bp.slot.services.slot import get_slot as svc_get_slot from bp.slot.services.slot import get_slot as svc_get_slot
from .slots import render_slot_main_panel
slot = await svc_get_slot(g.s, slot_id) if slot_id else None slot = await svc_get_slot(g.s, slot_id) if slot_id else None
if not slot: if not slot:
abort(404) abort(404)
@@ -251,7 +547,6 @@ async def _h_entry_content(calendar_slug=None, entry_id=None, **kw):
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
await _ensure_entry_context(entry_id) await _ensure_entry_context(entry_id)
from shared.sx.page import get_template_context from shared.sx.page import get_template_context
from .entries import _entry_main_panel_html
ctx = await get_template_context() ctx = await get_template_context()
return await _entry_main_panel_html(ctx) return await _entry_main_panel_html(ctx)
@@ -260,7 +555,6 @@ async def _h_entry_menu(calendar_slug=None, entry_id=None, **kw):
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
await _ensure_entry_context(entry_id) await _ensure_entry_context(entry_id)
from shared.sx.page import get_template_context from shared.sx.page import get_template_context
from .entries import _entry_nav_html
ctx = await get_template_context() ctx = await get_template_context()
return await _entry_nav_html(ctx) return await _entry_nav_html(ctx)
@@ -269,7 +563,6 @@ async def _h_entry_admin_content(calendar_slug=None, entry_id=None, **kw):
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
await _ensure_entry_context(entry_id) await _ensure_entry_context(entry_id)
from shared.sx.page import get_template_context from shared.sx.page import get_template_context
from .entries import _entry_admin_main_panel_html
ctx = await get_template_context() ctx = await get_template_context()
return await _entry_admin_main_panel_html(ctx) return await _entry_admin_main_panel_html(ctx)
@@ -287,7 +580,6 @@ async def _h_ticket_types_content(calendar_slug=None, entry_id=None,
entry = getattr(g, "entry", None) entry = getattr(g, "entry", None)
calendar = getattr(g, "calendar", None) calendar = getattr(g, "calendar", None)
from bp.ticket_types.services.tickets import list_ticket_types as svc_list_ticket_types from bp.ticket_types.services.tickets import list_ticket_types as svc_list_ticket_types
from .tickets import render_ticket_types_table
ticket_types = await svc_list_ticket_types(g.s, entry.id) if entry else [] ticket_types = await svc_list_ticket_types(g.s, entry.id) if entry else []
_add_to_defpage_ctx(ticket_types=ticket_types) _add_to_defpage_ctx(ticket_types=ticket_types)
return await render_ticket_types_table(ticket_types, entry, calendar, day, month, year) return await render_ticket_types_table(ticket_types, entry, calendar, day, month, year)
@@ -299,7 +591,6 @@ async def _h_ticket_type_content(calendar_slug=None, entry_id=None,
await _ensure_calendar(calendar_slug) await _ensure_calendar(calendar_slug)
await _ensure_entry(entry_id) await _ensure_entry(entry_id)
from bp.ticket_type.services.ticket import get_ticket_type as svc_get_ticket_type from bp.ticket_type.services.ticket import get_ticket_type as svc_get_ticket_type
from .tickets import render_ticket_type_main_panel
ticket_type = await svc_get_ticket_type(g.s, ticket_type_id) if ticket_type_id else None ticket_type = await svc_get_ticket_type(g.s, ticket_type_id) if ticket_type_id else None
if not ticket_type: if not ticket_type:
abort(404) abort(404)
@@ -314,7 +605,6 @@ async def _h_tickets_content(**kw):
from quart import g from quart import g
from shared.infrastructure.cart_identity import current_cart_identity from shared.infrastructure.cart_identity import current_cart_identity
from bp.tickets.services.tickets import get_user_tickets from bp.tickets.services.tickets import get_user_tickets
from .tickets import _tickets_main_panel_html
ident = current_cart_identity() ident = current_cart_identity()
tickets = await get_user_tickets( tickets = await get_user_tickets(
g.s, g.s,
@@ -330,7 +620,6 @@ async def _h_ticket_detail_content(code=None, **kw):
from quart import g, abort from quart import g, abort
from shared.infrastructure.cart_identity import current_cart_identity from shared.infrastructure.cart_identity import current_cart_identity
from bp.tickets.services.tickets import get_ticket_by_code from bp.tickets.services.tickets import get_ticket_by_code
from .tickets import _ticket_detail_panel_html
ticket = await get_ticket_by_code(g.s, code) if code else None ticket = await get_ticket_by_code(g.s, code) if code else None
if not ticket: if not ticket:
abort(404) abort(404)
@@ -354,7 +643,6 @@ async def _h_ticket_admin_content(**kw):
from sqlalchemy import select, func from sqlalchemy import select, func
from sqlalchemy.orm import selectinload from sqlalchemy.orm import selectinload
from models.calendars import CalendarEntry, Ticket from models.calendars import CalendarEntry, Ticket
from .tickets import _ticket_admin_main_panel_html
result = await g.s.execute( result = await g.s.execute(
select(Ticket) select(Ticket)
@@ -391,6 +679,5 @@ async def _h_ticket_admin_content(**kw):
async def _h_markets_content(**kw): async def _h_markets_content(**kw):
from shared.sx.page import get_template_context from shared.sx.page import get_template_context
from .calendar import _markets_main_panel_html
ctx = await get_template_context() ctx = await get_template_context()
return await _markets_main_panel_html(ctx) return await _markets_main_panel_html(ctx)

View File

@@ -1,10 +1,6 @@
"""SX docs defpage setup — registers layouts and page helpers.""" """SX docs defpage setup — registers layouts, page helpers, and loads .sx pages."""
from __future__ import annotations from __future__ import annotations
import os
from shared.sx.jinja_bridge import load_sx_dir, watch_sx_dir
def setup_sx_pages() -> None: def setup_sx_pages() -> None:
"""Register sx-specific layouts, page helpers, and load page definitions.""" """Register sx-specific layouts, page helpers, and load page definitions."""
@@ -17,8 +13,9 @@ def setup_sx_pages() -> None:
def _load_sx_page_files() -> None: def _load_sx_page_files() -> None:
"""Load defpage definitions from sx/sxc/pages/*.sx.""" """Load defpage definitions from sx/sxc/pages/*.sx."""
import os
from shared.sx.pages import load_page_dir from shared.sx.pages import load_page_dir
from shared.sx.jinja_bridge import load_service_components from shared.sx.jinja_bridge import load_sx_dir, watch_sx_dir, load_service_components
_sxc_dir = os.path.dirname(os.path.dirname(__file__)) # sx/sxc/ _sxc_dir = os.path.dirname(os.path.dirname(__file__)) # sx/sxc/
service_root = os.path.dirname(_sxc_dir) # sx/ service_root = os.path.dirname(_sxc_dir) # sx/
load_service_components(service_root, service_name="sx") load_service_components(service_root, service_name="sx")

View File

@@ -1,9 +1,107 @@
"""Individual content builder functions for sx docs pages.""" """All content generator functions and dispatchers for sx docs pages."""
from __future__ import annotations from __future__ import annotations
from .renders import _code, _example_code, _placeholder, _oob_code, _clear_components_btn from .renders import _code, _example_code, _placeholder, _oob_code, _clear_components_btn
from .utils import _attr_table_sx, _primitives_section_sx, _headers_table_sx from .utils import _attr_table_sx, _primitives_section_sx, _headers_table_sx
# ---------------------------------------------------------------------------
# Dispatcher functions — route slugs to content builders
# ---------------------------------------------------------------------------
async def _docs_content_sx(slug: str) -> str:
"""Route to the right docs content builder."""
import inspect
builders = {
"introduction": _docs_introduction_sx,
"getting-started": _docs_getting_started_sx,
"components": _docs_components_sx,
"evaluator": _docs_evaluator_sx,
"primitives": _docs_primitives_sx,
"css": _docs_css_sx,
"server-rendering": _docs_server_rendering_sx,
}
builder = builders.get(slug, _docs_introduction_sx)
result = builder()
return await result if inspect.isawaitable(result) else result
async def _reference_content_sx(slug: str) -> str:
import inspect
builders = {
"attributes": _reference_attrs_sx,
"headers": _reference_headers_sx,
"events": _reference_events_sx,
"js-api": _reference_js_api_sx,
}
result = builders.get(slug or "", _reference_attrs_sx)()
return await result if inspect.isawaitable(result) else result
def _protocol_content_sx(slug: str) -> str:
builders = {
"wire-format": _protocol_wire_format_sx,
"fragments": _protocol_fragments_sx,
"resolver-io": _protocol_resolver_io_sx,
"internal-services": _protocol_internal_services_sx,
"activitypub": _protocol_activitypub_sx,
"future": _protocol_future_sx,
}
return builders.get(slug, _protocol_wire_format_sx)()
def _examples_content_sx(slug: str) -> str:
builders = {
"click-to-load": _example_click_to_load_sx,
"form-submission": _example_form_submission_sx,
"polling": _example_polling_sx,
"delete-row": _example_delete_row_sx,
"inline-edit": _example_inline_edit_sx,
"oob-swaps": _example_oob_swaps_sx,
"lazy-loading": _example_lazy_loading_sx,
"infinite-scroll": _example_infinite_scroll_sx,
"progress-bar": _example_progress_bar_sx,
"active-search": _example_active_search_sx,
"inline-validation": _example_inline_validation_sx,
"value-select": _example_value_select_sx,
"reset-on-submit": _example_reset_on_submit_sx,
"edit-row": _example_edit_row_sx,
"bulk-update": _example_bulk_update_sx,
"swap-positions": _example_swap_positions_sx,
"select-filter": _example_select_filter_sx,
"tabs": _example_tabs_sx,
"animations": _example_animations_sx,
"dialogs": _example_dialogs_sx,
"keyboard-shortcuts": _example_keyboard_shortcuts_sx,
"put-patch": _example_put_patch_sx,
"json-encoding": _example_json_encoding_sx,
"vals-and-headers": _example_vals_and_headers_sx,
"loading-states": _example_loading_states_sx,
"sync-replace": _example_sync_replace_sx,
"retry": _example_retry_sx,
}
return builders.get(slug, _example_click_to_load_sx)()
def _essay_content_sx(slug: str) -> str:
builders = {
"sx-sucks": _essay_sx_sucks,
"why-sexps": _essay_why_sexps,
"htmx-react-hybrid": _essay_htmx_react_hybrid,
"on-demand-css": _essay_on_demand_css,
"client-reactivity": _essay_client_reactivity,
"sx-native": _essay_sx_native,
"sx-manifesto": _essay_sx_manifesto,
"tail-call-optimization": _essay_tail_call_optimization,
"continuations": _essay_continuations,
}
return builders.get(slug, _essay_sx_sucks)()
# ---------------------------------------------------------------------------
# Individual content builders
# ---------------------------------------------------------------------------
def _docs_introduction_sx() -> str: def _docs_introduction_sx() -> str:
return ( return (
'(~doc-page :title "Introduction"' '(~doc-page :title "Introduction"'

View File

@@ -1,117 +1,14 @@
"""Dispatcher functions, public partials, and page helper registration for sx docs.""" """Public partials and page helper registration for sx docs."""
from __future__ import annotations from __future__ import annotations
from .essays import ( from .essays import (
_docs_introduction_sx, _docs_getting_started_sx, _docs_components_sx, _docs_content_sx, _reference_content_sx, _protocol_content_sx,
_docs_evaluator_sx, _docs_primitives_sx, _docs_css_sx, _docs_server_rendering_sx, _examples_content_sx, _essay_content_sx,
_reference_index_sx, _reference_attr_detail_sx, _reference_attrs_sx, _reference_index_sx, _reference_attr_detail_sx,
_reference_headers_sx, _reference_events_sx, _reference_js_api_sx,
_protocol_wire_format_sx, _protocol_fragments_sx, _protocol_resolver_io_sx,
_protocol_internal_services_sx, _protocol_activitypub_sx, _protocol_future_sx,
_example_click_to_load_sx, _example_form_submission_sx, _example_polling_sx,
_example_delete_row_sx, _example_inline_edit_sx, _example_oob_swaps_sx,
_example_lazy_loading_sx, _example_infinite_scroll_sx, _example_progress_bar_sx,
_example_active_search_sx, _example_inline_validation_sx, _example_value_select_sx,
_example_reset_on_submit_sx, _example_edit_row_sx, _example_bulk_update_sx,
_example_swap_positions_sx, _example_select_filter_sx, _example_tabs_sx,
_example_animations_sx, _example_dialogs_sx, _example_keyboard_shortcuts_sx,
_example_put_patch_sx, _example_json_encoding_sx, _example_vals_and_headers_sx,
_example_loading_states_sx, _example_sync_replace_sx, _example_retry_sx,
_essay_sx_sucks, _essay_why_sexps, _essay_htmx_react_hybrid,
_essay_on_demand_css, _essay_client_reactivity, _essay_sx_native,
_essay_sx_manifesto, _essay_tail_call_optimization, _essay_continuations,
) )
from .utils import _docs_nav_sx, _reference_nav_sx, _protocols_nav_sx, _examples_nav_sx, _essays_nav_sx from .utils import _docs_nav_sx, _reference_nav_sx, _protocols_nav_sx, _examples_nav_sx, _essays_nav_sx
from content.highlight import highlight from content.highlight import highlight
async def _docs_content_sx(slug: str) -> str:
"""Route to the right docs content builder."""
import inspect
builders = {
"introduction": _docs_introduction_sx,
"getting-started": _docs_getting_started_sx,
"components": _docs_components_sx,
"evaluator": _docs_evaluator_sx,
"primitives": _docs_primitives_sx,
"css": _docs_css_sx,
"server-rendering": _docs_server_rendering_sx,
}
builder = builders.get(slug, _docs_introduction_sx)
result = builder()
return await result if inspect.isawaitable(result) else result
async def _reference_content_sx(slug: str) -> str:
import inspect
builders = {
"attributes": _reference_attrs_sx,
"headers": _reference_headers_sx,
"events": _reference_events_sx,
"js-api": _reference_js_api_sx,
}
result = builders.get(slug or "", _reference_attrs_sx)()
return await result if inspect.isawaitable(result) else result
def _protocol_content_sx(slug: str) -> str:
builders = {
"wire-format": _protocol_wire_format_sx,
"fragments": _protocol_fragments_sx,
"resolver-io": _protocol_resolver_io_sx,
"internal-services": _protocol_internal_services_sx,
"activitypub": _protocol_activitypub_sx,
"future": _protocol_future_sx,
}
return builders.get(slug, _protocol_wire_format_sx)()
def _examples_content_sx(slug: str) -> str:
builders = {
"click-to-load": _example_click_to_load_sx,
"form-submission": _example_form_submission_sx,
"polling": _example_polling_sx,
"delete-row": _example_delete_row_sx,
"inline-edit": _example_inline_edit_sx,
"oob-swaps": _example_oob_swaps_sx,
"lazy-loading": _example_lazy_loading_sx,
"infinite-scroll": _example_infinite_scroll_sx,
"progress-bar": _example_progress_bar_sx,
"active-search": _example_active_search_sx,
"inline-validation": _example_inline_validation_sx,
"value-select": _example_value_select_sx,
"reset-on-submit": _example_reset_on_submit_sx,
"edit-row": _example_edit_row_sx,
"bulk-update": _example_bulk_update_sx,
"swap-positions": _example_swap_positions_sx,
"select-filter": _example_select_filter_sx,
"tabs": _example_tabs_sx,
"animations": _example_animations_sx,
"dialogs": _example_dialogs_sx,
"keyboard-shortcuts": _example_keyboard_shortcuts_sx,
"put-patch": _example_put_patch_sx,
"json-encoding": _example_json_encoding_sx,
"vals-and-headers": _example_vals_and_headers_sx,
"loading-states": _example_loading_states_sx,
"sync-replace": _example_sync_replace_sx,
"retry": _example_retry_sx,
}
return builders.get(slug, _example_click_to_load_sx)()
def _essay_content_sx(slug: str) -> str:
builders = {
"sx-sucks": _essay_sx_sucks,
"why-sexps": _essay_why_sexps,
"htmx-react-hybrid": _essay_htmx_react_hybrid,
"on-demand-css": _essay_on_demand_css,
"client-reactivity": _essay_client_reactivity,
"sx-native": _essay_sx_native,
"sx-manifesto": _essay_sx_manifesto,
"tail-call-optimization": _essay_tail_call_optimization,
"continuations": _essay_continuations,
}
return builders.get(slug, _essay_sx_sucks)()
def home_content_sx() -> str: def home_content_sx() -> str:
"""Home page content as sx wire format.""" """Home page content as sx wire format."""