Slim events + sx sxc/pages/__init__.py → registration-only
Events: 3861 → 21 lines, split into 8 sub-modules (renders, helpers, layouts, calendar, entries, slots, tickets, utils). Updated 16 bp routes. SX Docs: 3224 → 27 lines, split into 5 sub-modules (renders, utils, essays, helpers, layouts). Updated 37 import sites in bp/pages/routes.py. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -25,7 +25,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/click")
|
||||
async def api_click():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||
sx_src = f'(~click-result :time "{now}")'
|
||||
comp_text = _component_source_text("click-result")
|
||||
@@ -38,7 +38,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/form")
|
||||
async def api_form():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
form = await request.form
|
||||
name = form.get("name", "")
|
||||
escaped = name.replace('"', '\\"')
|
||||
@@ -54,7 +54,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/poll")
|
||||
async def api_poll():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
_poll_count["n"] += 1
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
count = min(_poll_count["n"], 10)
|
||||
@@ -69,7 +69,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.delete("/examples/api/delete/<item_id>")
|
||||
async def api_delete(item_id: str):
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
# Empty primary response — outerHTML swap removes the row
|
||||
# But send OOB swaps to show what happened
|
||||
wire_text = _full_wire_text(f'(empty — row #{item_id} removed by outerHTML swap)')
|
||||
@@ -81,7 +81,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/edit")
|
||||
async def api_edit_form():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
value = request.args.get("value", "")
|
||||
escaped = value.replace('"', '\\"')
|
||||
sx_src = f'(~inline-edit-form :value "{escaped}")'
|
||||
@@ -95,7 +95,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/edit")
|
||||
async def api_edit_save():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
form = await request.form
|
||||
value = form.get("value", "")
|
||||
escaped = value.replace('"', '\\"')
|
||||
@@ -109,7 +109,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/edit/cancel")
|
||||
async def api_edit_cancel():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
value = request.args.get("value", "")
|
||||
escaped = value.replace('"', '\\"')
|
||||
sx_src = f'(~inline-view :value "{escaped}")'
|
||||
@@ -122,7 +122,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/oob")
|
||||
async def api_oob():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _full_wire_text
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
sx_src = (
|
||||
f'(<>'
|
||||
@@ -141,7 +141,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/lazy")
|
||||
async def api_lazy():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
sx_src = f'(~lazy-result :time "{now}")'
|
||||
comp_text = _component_source_text("lazy-result")
|
||||
@@ -155,7 +155,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/scroll")
|
||||
async def api_scroll():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _full_wire_text
|
||||
page = int(request.args.get("page", 2))
|
||||
start = (page - 1) * 5 + 1
|
||||
next_page = page + 1
|
||||
@@ -191,7 +191,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/progress/start")
|
||||
async def api_progress_start():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
job_id = str(uuid4())[:8]
|
||||
_jobs[job_id] = 0
|
||||
sx_src = f'(~progress-status :percent 0 :job-id "{job_id}")'
|
||||
@@ -204,7 +204,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/progress/status")
|
||||
async def api_progress_status():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
job_id = request.args.get("job", "")
|
||||
current = _jobs.get(job_id, 0)
|
||||
current = min(current + random.randint(15, 30), 100)
|
||||
@@ -221,7 +221,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/search")
|
||||
async def api_search():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
from content.pages import SEARCH_LANGUAGES
|
||||
q = request.args.get("q", "").strip().lower()
|
||||
if not q:
|
||||
@@ -244,7 +244,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/validate")
|
||||
async def api_validate():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
email = request.args.get("email", "").strip()
|
||||
if not email:
|
||||
sx_src = '(~validation-error :message "Email is required")'
|
||||
@@ -282,7 +282,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/values")
|
||||
async def api_values():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _full_wire_text
|
||||
from content.pages import VALUE_SELECT_DATA
|
||||
cat = request.args.get("category", "")
|
||||
items = VALUE_SELECT_DATA.get(cat, [])
|
||||
@@ -300,7 +300,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/reset-submit")
|
||||
async def api_reset_submit():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
form = await request.form
|
||||
msg = form.get("message", "").strip() or "(empty)"
|
||||
escaped = msg.replace('"', '\\"')
|
||||
@@ -326,7 +326,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/editrow/<row_id>")
|
||||
async def api_editrow_form(row_id: str):
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
rows = _get_edit_rows()
|
||||
row = rows.get(row_id, {"id": row_id, "name": "", "price": "0", "stock": "0"})
|
||||
sx_src = (f'(~edit-row-form :id "{row["id"]}" :name "{row["name"]}"'
|
||||
@@ -341,7 +341,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/editrow/<row_id>")
|
||||
async def api_editrow_save(row_id: str):
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
form = await request.form
|
||||
rows = _get_edit_rows()
|
||||
rows[row_id] = {
|
||||
@@ -362,7 +362,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/editrow/<row_id>/cancel")
|
||||
async def api_editrow_cancel(row_id: str):
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
rows = _get_edit_rows()
|
||||
row = rows.get(row_id, {"id": row_id, "name": "", "price": "0", "stock": "0"})
|
||||
sx_src = (f'(~edit-row-view :id "{row["id"]}" :name "{row["name"]}"'
|
||||
@@ -388,7 +388,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/bulk")
|
||||
async def api_bulk():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
action = request.args.get("action", "activate")
|
||||
form = await request.form
|
||||
ids = form.getlist("ids")
|
||||
@@ -418,7 +418,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/swap-log")
|
||||
async def api_swap_log():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _full_wire_text
|
||||
mode = request.args.get("mode", "beforeend")
|
||||
_swap_count["n"] += 1
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
@@ -438,7 +438,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/dashboard")
|
||||
async def api_dashboard():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _full_wire_text
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
sx_src = (
|
||||
f'(<>'
|
||||
@@ -483,7 +483,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/tabs/<tab>")
|
||||
async def api_tabs(tab: str):
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _full_wire_text
|
||||
sx_src = _TAB_CONTENT.get(tab, _TAB_CONTENT["tab1"])
|
||||
buttons = []
|
||||
for t, label in [("tab1", "Overview"), ("tab2", "Details"), ("tab3", "History")]:
|
||||
@@ -503,7 +503,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/animate")
|
||||
async def api_animate():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
colors = ["bg-violet-100", "bg-emerald-100", "bg-blue-100", "bg-amber-100", "bg-rose-100"]
|
||||
color = random.choice(colors)
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
@@ -519,7 +519,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/dialog")
|
||||
async def api_dialog():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
sx_src = '(~dialog-modal :title "Confirm Action" :message "Are you sure you want to proceed? This is a demo dialog rendered entirely with sx components.")'
|
||||
comp_text = _component_source_text("dialog-modal")
|
||||
wire_text = _full_wire_text(sx_src, "dialog-modal")
|
||||
@@ -530,7 +530,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/dialog/close")
|
||||
async def api_dialog_close():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _full_wire_text
|
||||
wire_text = _full_wire_text("(empty — dialog closed)")
|
||||
oob_wire = _oob_code("dialog-wire", wire_text)
|
||||
return sx_response(f'(<> {oob_wire})')
|
||||
@@ -546,7 +546,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/keyboard")
|
||||
async def api_keyboard():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
key = request.args.get("key", "")
|
||||
action = _KBD_ACTIONS.get(key, f"Unknown key: {key}")
|
||||
escaped_action = action.replace('"', '\\"')
|
||||
@@ -571,7 +571,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/putpatch/edit-all")
|
||||
async def api_pp_edit_all():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
p = _get_profile()
|
||||
sx_src = f'(~pp-form-full :name "{p["name"]}" :email "{p["email"]}" :role "{p["role"]}")'
|
||||
comp_text = _component_source_text("pp-form-full")
|
||||
@@ -584,7 +584,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.put("/examples/api/putpatch")
|
||||
async def api_pp_put():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
form = await request.form
|
||||
p = _get_profile()
|
||||
p["name"] = form.get("name", p["name"])
|
||||
@@ -600,7 +600,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/putpatch/cancel")
|
||||
async def api_pp_cancel():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
p = _get_profile()
|
||||
sx_src = f'(~pp-view :name "{p["name"]}" :email "{p["email"]}" :role "{p["role"]}")'
|
||||
comp_text = _component_source_text("pp-view")
|
||||
@@ -615,7 +615,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.post("/examples/api/json-echo")
|
||||
async def api_json_echo():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
data = await request.get_json(silent=True) or {}
|
||||
body = json.dumps(data, indent=2)
|
||||
ct = request.content_type or "unknown"
|
||||
@@ -633,7 +633,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/echo-vals")
|
||||
async def api_echo_vals():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
vals = {k: v for k, v in request.args.items()
|
||||
if k not in ("_", "sx-request")}
|
||||
items_sx = " ".join(f'"{k}: {v}"' for k, v in vals.items())
|
||||
@@ -647,7 +647,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/echo-headers")
|
||||
async def api_echo_headers():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
custom = {k: v for k, v in request.headers if k.lower().startswith("x-")}
|
||||
items_sx = " ".join(f'"{k}: {v}"' for k, v in custom.items())
|
||||
sx_src = f'(~echo-result :label "headers" :items (list {items_sx}))'
|
||||
@@ -662,7 +662,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/slow")
|
||||
async def api_slow():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
await asyncio.sleep(2)
|
||||
now = datetime.now().strftime("%H:%M:%S")
|
||||
sx_src = f'(~loading-result :time "{now}")'
|
||||
@@ -677,7 +677,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/slow-search")
|
||||
async def api_slow_search():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
delay = random.uniform(0.5, 2.0)
|
||||
await asyncio.sleep(delay)
|
||||
q = request.args.get("q", "").strip()
|
||||
@@ -697,7 +697,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
@bp.get("/examples/api/flaky")
|
||||
async def api_flaky():
|
||||
from shared.sx.helpers import sx_response
|
||||
from sxc.pages import _oob_code, _component_source_text, _full_wire_text
|
||||
from sxc.pages.renders import _oob_code, _component_source_text, _full_wire_text
|
||||
_flaky["n"] += 1
|
||||
n = _flaky["n"]
|
||||
if n % 3 != 0:
|
||||
@@ -715,7 +715,7 @@ def register(url_prefix: str = "/") -> Blueprint:
|
||||
|
||||
def _ref_wire(wire_id: str, sx_src: str) -> str:
|
||||
"""Build OOB swap showing the wire response text."""
|
||||
from sxc.pages import _oob_code
|
||||
from sxc.pages.renders import _oob_code
|
||||
return _oob_code(f"ref-wire-{wire_id}", sx_src)
|
||||
|
||||
@bp.get("/reference/api/time")
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
2615
sx/sxc/pages/essays.py
Normal file
2615
sx/sxc/pages/essays.py
Normal file
File diff suppressed because it is too large
Load Diff
239
sx/sxc/pages/helpers.py
Normal file
239
sx/sxc/pages/helpers.py
Normal file
@@ -0,0 +1,239 @@
|
||||
"""Dispatcher functions, public partials, and page helper registration for sx docs."""
|
||||
from __future__ import annotations
|
||||
|
||||
from .essays import (
|
||||
_docs_introduction_sx, _docs_getting_started_sx, _docs_components_sx,
|
||||
_docs_evaluator_sx, _docs_primitives_sx, _docs_css_sx, _docs_server_rendering_sx,
|
||||
_reference_index_sx, _reference_attr_detail_sx, _reference_attrs_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 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:
|
||||
"""Home page content as sx wire format."""
|
||||
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'(section :id "main-panel"'
|
||||
f' :class "flex-1 md:h-full md:min-h-0 overflow-y-auto overscroll-contain js-grid-viewport"'
|
||||
f' (div :id "main-content"'
|
||||
f' (~sx-hero {hero_code})'
|
||||
f' (~sx-philosophy)'
|
||||
f' (~sx-how-it-works)'
|
||||
f' (~sx-credits)))'
|
||||
)
|
||||
|
||||
|
||||
async def docs_content_partial_sx(slug: str) -> str:
|
||||
"""Docs content as sx wire format."""
|
||||
inner = await _docs_content_sx(slug)
|
||||
return (
|
||||
f'(section :id "main-panel"'
|
||||
f' :class "flex-1 md:h-full md:min-h-0 overflow-y-auto overscroll-contain js-grid-viewport"'
|
||||
f' {inner})'
|
||||
)
|
||||
|
||||
|
||||
async def reference_content_partial_sx(slug: str) -> str:
|
||||
inner = await _reference_content_sx(slug)
|
||||
return (
|
||||
f'(section :id "main-panel"'
|
||||
f' :class "flex-1 md:h-full md:min-h-0 overflow-y-auto overscroll-contain js-grid-viewport"'
|
||||
f' {inner})'
|
||||
)
|
||||
|
||||
|
||||
async def protocol_content_partial_sx(slug: str) -> str:
|
||||
inner = await _protocol_content_sx(slug)
|
||||
return (
|
||||
f'(section :id "main-panel"'
|
||||
f' :class "flex-1 md:h-full md:min-h-0 overflow-y-auto overscroll-contain js-grid-viewport"'
|
||||
f' {inner})'
|
||||
)
|
||||
|
||||
|
||||
async def examples_content_partial_sx(slug: str) -> str:
|
||||
inner = await _examples_content_sx(slug)
|
||||
return (
|
||||
f'(section :id "main-panel"'
|
||||
f' :class "flex-1 md:h-full md:min-h-0 overflow-y-auto overscroll-contain js-grid-viewport"'
|
||||
f' {inner})'
|
||||
)
|
||||
|
||||
|
||||
async def essay_content_partial_sx(slug: str) -> str:
|
||||
inner = await _essay_content_sx(slug)
|
||||
return (
|
||||
f'(section :id "main-panel"'
|
||||
f' :class "flex-1 md:h-full md:min-h-0 overflow-y-auto overscroll-contain js-grid-viewport"'
|
||||
f' {inner})'
|
||||
)
|
||||
|
||||
|
||||
def _register_sx_helpers() -> None:
|
||||
"""Register Python content builder functions as page helpers."""
|
||||
from shared.sx.pages import register_page_helpers
|
||||
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,
|
||||
"reference-index-content": _reference_index_sx,
|
||||
"reference-attr-detail": _reference_attr_detail_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,
|
||||
})
|
||||
112
sx/sxc/pages/layouts.py
Normal file
112
sx/sxc/pages/layouts.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""Layout registration and header/mobile functions for sx docs."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from .utils import _main_nav_sx, _sx_header_sx, _sub_row_sx
|
||||
|
||||
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)
|
||||
|
||||
|
||||
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, _ctx_to_env
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
main_nav = await _main_nav_sx(kw.get("section"))
|
||||
sx_row = await _sx_header_sx(main_nav)
|
||||
return await render_to_sx_with_env("sx-layout-full", _ctx_to_env(ctx),
|
||||
sx_row=SxExpr(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, _ctx_to_env, oob_header_sx
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
main_nav = await _main_nav_sx(kw.get("section"))
|
||||
sx_row = await _sx_header_sx(main_nav)
|
||||
rows = await render_to_sx_with_env("sx-layout-full", _ctx_to_env(ctx),
|
||||
sx_row=SxExpr(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, _ctx_to_env
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
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", "")
|
||||
|
||||
main_nav = await _main_nav_sx(section)
|
||||
sub_row = await _sub_row_sx(sub_label, sub_href, sub_nav, selected)
|
||||
sx_row = await _sx_header_sx(main_nav, child=sub_row)
|
||||
return await render_to_sx_with_env("sx-section-layout-full", _ctx_to_env(ctx),
|
||||
sx_row=SxExpr(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, _ctx_to_env, oob_header_sx
|
||||
from shared.sx.parser import SxExpr
|
||||
|
||||
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", "")
|
||||
|
||||
main_nav = await _main_nav_sx(section)
|
||||
sub_row = await _sub_row_sx(sub_label, sub_href, sub_nav, selected)
|
||||
sx_row = await _sx_header_sx(main_nav, child=sub_row)
|
||||
rows = await render_to_sx_with_env("sx-section-layout-full", _ctx_to_env(ctx),
|
||||
sx_row=SxExpr(sx_row))
|
||||
return await oob_header_sx("root-header-child", "sx-header-child", rows)
|
||||
|
||||
|
||||
async 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, render_to_sx, SxExpr,
|
||||
)
|
||||
|
||||
main_nav = await _main_nav_sx(kw.get("section"))
|
||||
return mobile_menu_sx(
|
||||
await render_to_sx("mobile-menu-section",
|
||||
label="sx", href="/", level=1, colour="violet",
|
||||
items=SxExpr(main_nav)),
|
||||
await mobile_root_nav_sx(ctx),
|
||||
)
|
||||
|
||||
|
||||
async 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, render_to_sx, SxExpr,
|
||||
)
|
||||
|
||||
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 = await _main_nav_sx(section)
|
||||
|
||||
parts = []
|
||||
if sub_nav:
|
||||
parts.append(await render_to_sx("mobile-menu-section",
|
||||
label=sub_label, href=sub_href, level=2, colour="violet",
|
||||
items=SxExpr(sub_nav)))
|
||||
parts.append(await render_to_sx("mobile-menu-section",
|
||||
label="sx", href="/", level=1, colour="violet",
|
||||
items=SxExpr(main_nav)))
|
||||
parts.append(await mobile_root_nav_sx(ctx))
|
||||
return mobile_menu_sx(*parts)
|
||||
92
sx/sxc/pages/renders.py
Normal file
92
sx/sxc/pages/renders.py
Normal file
@@ -0,0 +1,92 @@
|
||||
"""Public render/utility functions called from bp routes."""
|
||||
from __future__ import annotations
|
||||
|
||||
from content.highlight import highlight
|
||||
|
||||
|
||||
def _code(code: str, language: str = "lisp") -> str:
|
||||
"""Build a ~doc-code component with highlighted content."""
|
||||
highlighted = highlight(code, language)
|
||||
return f'(~doc-code :code {highlighted})'
|
||||
|
||||
|
||||
def _example_code(code: str, language: str = "lisp") -> str:
|
||||
"""Build an ~example-source component with highlighted content."""
|
||||
highlighted = highlight(code, language)
|
||||
return f'(~example-source :code {highlighted})'
|
||||
|
||||
|
||||
def _placeholder(div_id: str) -> str:
|
||||
"""Empty placeholder that will be filled by OOB swap on interaction."""
|
||||
return (f'(div :id "{div_id}"'
|
||||
f' (div :class "bg-stone-50 border border-stone-200 rounded p-4 mt-3"'
|
||||
f' (p :class "text-stone-400 italic text-sm"'
|
||||
f' "Trigger the demo to see the actual content.")))')
|
||||
|
||||
|
||||
def _component_source_text(*names: str) -> str:
|
||||
"""Get defcomp source text for named components."""
|
||||
from shared.sx.jinja_bridge import _COMPONENT_ENV
|
||||
from shared.sx.types import Component
|
||||
from shared.sx.parser import serialize
|
||||
parts = []
|
||||
for name in names:
|
||||
key = name if name.startswith("~") else f"~{name}"
|
||||
val = _COMPONENT_ENV.get(key)
|
||||
if isinstance(val, Component):
|
||||
param_strs = ["&key"] + list(val.params)
|
||||
if val.has_children:
|
||||
param_strs.extend(["&rest", "children"])
|
||||
params_sx = "(" + " ".join(param_strs) + ")"
|
||||
body_sx = serialize(val.body, pretty=True)
|
||||
parts.append(f"(defcomp ~{val.name} {params_sx}\n{body_sx})")
|
||||
return "\n\n".join(parts)
|
||||
|
||||
|
||||
def _oob_code(target_id: str, text: str) -> str:
|
||||
"""OOB swap that displays plain code in a styled block."""
|
||||
escaped = text.replace('\\', '\\\\').replace('"', '\\"')
|
||||
return (f'(div :id "{target_id}" :sx-swap-oob "innerHTML"'
|
||||
f' (div :class "bg-stone-50 border border-stone-200 rounded p-4 mt-3 overflow-x-auto"'
|
||||
f' (pre :class "text-sm whitespace-pre-wrap"'
|
||||
f' (code "{escaped}"))))')
|
||||
|
||||
|
||||
def _clear_components_btn() -> str:
|
||||
"""Button that clears the client-side component cache (localStorage + in-memory)."""
|
||||
js = ("localStorage.removeItem('sx-components-hash');"
|
||||
"localStorage.removeItem('sx-components-src');"
|
||||
"var e=Sx.getEnv();Object.keys(e).forEach(function(k){if(k.charAt(0)==='~')delete e[k]});"
|
||||
"var b=this;b.textContent='Cleared!';setTimeout(function(){b.textContent='Clear component cache'},2000)")
|
||||
return (f'(button :onclick "{js}"'
|
||||
f' :class "text-xs text-stone-400 hover:text-stone-600 border border-stone-200'
|
||||
f' rounded px-2 py-1 transition-colors"'
|
||||
f' "Clear component cache")')
|
||||
|
||||
|
||||
def _full_wire_text(sx_src: str, *comp_names: str) -> str:
|
||||
"""Build the full wire response text showing component defs + CSS note + sx source.
|
||||
|
||||
Only includes component definitions the client doesn't already have,
|
||||
matching the real behaviour of sx_response().
|
||||
"""
|
||||
from quart import request
|
||||
parts = []
|
||||
if comp_names:
|
||||
# Check which components the client already has
|
||||
loaded_raw = request.headers.get("SX-Components", "")
|
||||
loaded = set(loaded_raw.split(",")) if loaded_raw else set()
|
||||
missing = [n for n in comp_names
|
||||
if f"~{n}" not in loaded and n not in loaded]
|
||||
if missing:
|
||||
comp_text = _component_source_text(*missing)
|
||||
if comp_text:
|
||||
parts.append(f'<script type="text/sx" data-components>\n{comp_text}\n</script>')
|
||||
parts.append('<style data-sx-css>/* new CSS rules */</style>')
|
||||
# Pretty-print the sx source for readable display
|
||||
try:
|
||||
from shared.sx.parser import parse as _parse, serialize as _serialize
|
||||
parts.append(_serialize(_parse(sx_src), pretty=True))
|
||||
except Exception:
|
||||
parts.append(sx_src)
|
||||
return "\n\n".join(parts)
|
||||
137
sx/sxc/pages/utils.py
Normal file
137
sx/sxc/pages/utils.py
Normal file
@@ -0,0 +1,137 @@
|
||||
"""Shared utility functions for sx docs pages."""
|
||||
from __future__ import annotations
|
||||
|
||||
from shared.sx.helpers import (
|
||||
render_to_sx, SxExpr,
|
||||
)
|
||||
|
||||
|
||||
async def _nav_items_sx(items: list[tuple[str, str]], current: str | None = None) -> str:
|
||||
"""Build nav link items as sx."""
|
||||
parts = []
|
||||
for label, href in items:
|
||||
parts.append(await render_to_sx("nav-link",
|
||||
href=href, label=label,
|
||||
is_selected="true" if current == label else None,
|
||||
select_colours="aria-selected:bg-violet-200 aria-selected:text-violet-900",
|
||||
))
|
||||
return "(<> " + " ".join(parts) + ")"
|
||||
|
||||
|
||||
async def _doc_nav_sx(items: list[tuple[str, str]], current: str) -> str:
|
||||
"""Build the in-page doc navigation pills."""
|
||||
items_sx = " ".join(
|
||||
f'(list "{label}" "{href}")'
|
||||
for label, href in items
|
||||
)
|
||||
return await render_to_sx("doc-nav", items=SxExpr(f"(list {items_sx})"), current=current)
|
||||
|
||||
|
||||
async def _attr_table_sx(title: str, attrs: list[tuple[str, str, bool]]) -> str:
|
||||
"""Build an attribute reference table."""
|
||||
from content.pages import ATTR_DETAILS
|
||||
rows = []
|
||||
for attr, desc, exists in attrs:
|
||||
href = f"/reference/attributes/{attr}" if exists and attr in ATTR_DETAILS else None
|
||||
rows.append(await render_to_sx("doc-attr-row", attr=attr, description=desc,
|
||||
exists="true" if exists else None,
|
||||
href=href))
|
||||
return (
|
||||
f'(div :class "space-y-3"'
|
||||
f' (h3 :class "text-xl font-semibold text-stone-700" "{title}")'
|
||||
f' (div :class "overflow-x-auto rounded border border-stone-200"'
|
||||
f' (table :class "w-full text-left text-sm"'
|
||||
f' (thead (tr :class "border-b border-stone-200 bg-stone-50"'
|
||||
f' (th :class "px-3 py-2 font-medium text-stone-600" "Attribute")'
|
||||
f' (th :class "px-3 py-2 font-medium text-stone-600" "Description")'
|
||||
f' (th :class "px-3 py-2 font-medium text-stone-600 text-center w-20" "In sx?")))'
|
||||
f' (tbody {" ".join(rows)}))))'
|
||||
)
|
||||
|
||||
|
||||
def _headers_table_sx(title: str, headers: list[tuple[str, str, str]]) -> str:
|
||||
"""Build a headers reference table."""
|
||||
rows = []
|
||||
for name, value, desc in headers:
|
||||
rows.append(
|
||||
f'(tr :class "border-b border-stone-100"'
|
||||
f' (td :class "px-3 py-2 font-mono text-sm text-violet-700 whitespace-nowrap" "{name}")'
|
||||
f' (td :class "px-3 py-2 font-mono text-sm text-stone-500" "{value}")'
|
||||
f' (td :class "px-3 py-2 text-stone-700 text-sm" "{desc}"))'
|
||||
)
|
||||
return (
|
||||
f'(div :class "space-y-3"'
|
||||
f' (h3 :class "text-xl font-semibold text-stone-700" "{title}")'
|
||||
f' (div :class "overflow-x-auto rounded border border-stone-200"'
|
||||
f' (table :class "w-full text-left text-sm"'
|
||||
f' (thead (tr :class "border-b border-stone-200 bg-stone-50"'
|
||||
f' (th :class "px-3 py-2 font-medium text-stone-600" "Header")'
|
||||
f' (th :class "px-3 py-2 font-medium text-stone-600" "Value")'
|
||||
f' (th :class "px-3 py-2 font-medium text-stone-600" "Description")))'
|
||||
f' (tbody {" ".join(rows)}))))'
|
||||
)
|
||||
|
||||
|
||||
async def _primitives_section_sx() -> str:
|
||||
"""Build the primitives section."""
|
||||
from content.pages import PRIMITIVES
|
||||
parts = []
|
||||
for category, prims in PRIMITIVES.items():
|
||||
prims_sx = " ".join(f'"{p}"' for p in prims)
|
||||
parts.append(await render_to_sx("doc-primitives-table",
|
||||
category=category,
|
||||
primitives=SxExpr(f"(list {prims_sx})")))
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
async def _sx_header_sx(nav: str | None = None, *, child: str | None = None) -> str:
|
||||
"""Build the sx docs menu-row."""
|
||||
return await render_to_sx("menu-row-sx",
|
||||
id="sx-row", level=1, colour="violet",
|
||||
link_href="/", link_label="sx",
|
||||
link_label_content=SxExpr('(span :class "font-mono" "(<x>)")'),
|
||||
nav=SxExpr(nav) if nav else None,
|
||||
child_id="sx-header-child",
|
||||
child=SxExpr(child) if child else None,
|
||||
)
|
||||
|
||||
|
||||
async def _docs_nav_sx(current: str | None = None) -> str:
|
||||
from content.pages import DOCS_NAV
|
||||
return await _nav_items_sx(DOCS_NAV, current)
|
||||
|
||||
|
||||
async def _reference_nav_sx(current: str | None = None) -> str:
|
||||
from content.pages import REFERENCE_NAV
|
||||
return await _nav_items_sx(REFERENCE_NAV, current)
|
||||
|
||||
|
||||
async def _protocols_nav_sx(current: str | None = None) -> str:
|
||||
from content.pages import PROTOCOLS_NAV
|
||||
return await _nav_items_sx(PROTOCOLS_NAV, current)
|
||||
|
||||
|
||||
async def _examples_nav_sx(current: str | None = None) -> str:
|
||||
from content.pages import EXAMPLES_NAV
|
||||
return await _nav_items_sx(EXAMPLES_NAV, current)
|
||||
|
||||
|
||||
async def _essays_nav_sx(current: str | None = None) -> str:
|
||||
from content.pages import ESSAYS_NAV
|
||||
return await _nav_items_sx(ESSAYS_NAV, current)
|
||||
|
||||
|
||||
async def _main_nav_sx(current_section: str | None = None) -> str:
|
||||
from content.pages import MAIN_NAV
|
||||
return await _nav_items_sx(MAIN_NAV, current_section)
|
||||
|
||||
|
||||
async def _sub_row_sx(sub_label: str, sub_href: str, sub_nav: str,
|
||||
selected: str = "") -> str:
|
||||
"""Build the level-2 sub-section menu-row."""
|
||||
return await render_to_sx("menu-row-sx",
|
||||
id="sx-sub-row", level=2, colour="violet",
|
||||
link_href=sub_href, link_label=sub_label,
|
||||
selected=selected or None,
|
||||
nav=SxExpr(sub_nav),
|
||||
)
|
||||
Reference in New Issue
Block a user