Send all responses as sexp wire format with client-side rendering
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 5m35s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 5m35s
- Server sends sexp source text, client (sexp.js) renders everything - SexpExpr marker class for nested sexp composition in serialize() - sexp_page() HTML shell with data-mount="body" for full page loads - sexp_response() returns text/sexp for OOB/partial responses - ~app-body layout component replaces ~app-layout (no raw!) - ~rich-text is the only component using raw! (for CMS HTML content) - Fragment endpoints return text/sexp, auto-wrapped in SexpExpr - All _*_html() helpers converted to _*_sexp() returning sexp source - Head auto-hoist: sexp.js moves meta/title/link/script[ld+json] from rendered body to document.head automatically - Unknown components render warning box instead of crashing page - Component kwargs preserve AST for lazy rendering (fixes <> in kwargs) - Fix unterminated paren in events/sexp/tickets.sexpr Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -12,6 +12,7 @@ from quart import (
|
||||
)
|
||||
from shared.browser.app.authz import require_admin, require_post_author
|
||||
from shared.browser.app.utils.htmx import is_htmx_request
|
||||
from shared.sexp.helpers import sexp_response
|
||||
from shared.utils import host_url
|
||||
|
||||
def register():
|
||||
@@ -58,10 +59,10 @@ def register():
|
||||
tctx.update(ctx)
|
||||
if not is_htmx_request():
|
||||
html = await render_post_admin_page(tctx)
|
||||
return await make_response(html)
|
||||
else:
|
||||
html = await render_post_admin_oob(tctx)
|
||||
|
||||
return await make_response(html)
|
||||
sexp_src = await render_post_admin_oob(tctx)
|
||||
return sexp_response(sexp_src)
|
||||
|
||||
@bp.put("/features/")
|
||||
@require_admin
|
||||
@@ -105,7 +106,7 @@ def register():
|
||||
sumup_merchant_code=result.get("sumup_merchant_code") or "",
|
||||
sumup_checkout_prefix=result.get("sumup_checkout_prefix") or "",
|
||||
)
|
||||
return await make_response(html)
|
||||
return sexp_response(html)
|
||||
|
||||
@bp.put("/admin/sumup/")
|
||||
@require_admin
|
||||
@@ -144,7 +145,7 @@ def register():
|
||||
sumup_merchant_code=result.get("sumup_merchant_code") or "",
|
||||
sumup_checkout_prefix=result.get("sumup_checkout_prefix") or "",
|
||||
)
|
||||
return await make_response(html)
|
||||
return sexp_response(html)
|
||||
|
||||
@bp.get("/data/")
|
||||
@require_admin
|
||||
@@ -157,10 +158,10 @@ def register():
|
||||
tctx["data_html"] = data_html
|
||||
if not is_htmx_request():
|
||||
html = await render_post_data_page(tctx)
|
||||
return await make_response(html)
|
||||
else:
|
||||
html = await render_post_data_oob(tctx)
|
||||
|
||||
return await make_response(html)
|
||||
sexp_src = await render_post_data_oob(tctx)
|
||||
return sexp_response(sexp_src)
|
||||
|
||||
@bp.get("/entries/calendar/<int:calendar_id>/")
|
||||
@require_admin
|
||||
@@ -280,10 +281,10 @@ def register():
|
||||
tctx["entries_html"] = entries_html
|
||||
if not is_htmx_request():
|
||||
html = await render_post_entries_page(tctx)
|
||||
return await make_response(html)
|
||||
else:
|
||||
html = await render_post_entries_oob(tctx)
|
||||
|
||||
return await make_response(html)
|
||||
sexp_src = await render_post_entries_oob(tctx)
|
||||
return sexp_response(sexp_src)
|
||||
|
||||
@bp.post("/entries/<int:entry_id>/toggle/")
|
||||
@require_admin
|
||||
@@ -335,7 +336,7 @@ def register():
|
||||
admin_list = render_associated_entries(all_calendars, associated_entry_ids, post["slug"])
|
||||
nav_entries_html = render_nav_entries_oob(associated_entries, calendars, post)
|
||||
|
||||
return await make_response(admin_list + nav_entries_html)
|
||||
return sexp_response(admin_list + nav_entries_html)
|
||||
|
||||
@bp.get("/settings/")
|
||||
@require_post_author
|
||||
@@ -359,10 +360,10 @@ def register():
|
||||
tctx["settings_html"] = settings_html
|
||||
if not is_htmx_request():
|
||||
html = await render_post_settings_page(tctx)
|
||||
return await make_response(html)
|
||||
else:
|
||||
html = await render_post_settings_oob(tctx)
|
||||
|
||||
return await make_response(html)
|
||||
sexp_src = await render_post_settings_oob(tctx)
|
||||
return sexp_response(sexp_src)
|
||||
|
||||
@bp.post("/settings/")
|
||||
@require_post_author
|
||||
@@ -465,10 +466,10 @@ def register():
|
||||
tctx["edit_html"] = edit_html
|
||||
if not is_htmx_request():
|
||||
html = await render_post_edit_page(tctx)
|
||||
return await make_response(html)
|
||||
else:
|
||||
html = await render_post_edit_oob(tctx)
|
||||
|
||||
return await make_response(html)
|
||||
sexp_src = await render_post_edit_oob(tctx)
|
||||
return sexp_response(sexp_src)
|
||||
|
||||
@bp.post("/edit/")
|
||||
@require_post_author
|
||||
@@ -598,8 +599,7 @@ def register():
|
||||
page_markets = await _fetch_page_markets(post_id)
|
||||
|
||||
from sexp.sexp_components import render_markets_panel
|
||||
html = render_markets_panel(page_markets, post)
|
||||
return await make_response(html)
|
||||
return sexp_response(render_markets_panel(page_markets, post))
|
||||
|
||||
@bp.post("/markets/new/")
|
||||
@require_admin
|
||||
@@ -625,8 +625,7 @@ def register():
|
||||
page_markets = await _fetch_page_markets(post_id)
|
||||
|
||||
from sexp.sexp_components import render_markets_panel
|
||||
html = render_markets_panel(page_markets, post)
|
||||
return await make_response(html)
|
||||
return sexp_response(render_markets_panel(page_markets, post))
|
||||
|
||||
@bp.delete("/markets/<market_slug>/")
|
||||
@require_admin
|
||||
@@ -646,7 +645,6 @@ def register():
|
||||
page_markets = await _fetch_page_markets(post_id)
|
||||
|
||||
from sexp.sexp_components import render_markets_panel
|
||||
html = render_markets_panel(page_markets, post)
|
||||
return await make_response(html)
|
||||
return sexp_response(render_markets_panel(page_markets, post))
|
||||
|
||||
return bp
|
||||
|
||||
Reference in New Issue
Block a user