Enable cross-subdomain htmx and purify layout to sexp
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m15s

- Disable htmx selfRequestsOnly, add CORS headers for *.rose-ash.com
- Remove same-origin guards from ~menu-row and ~nav-link htmx attrs
- Convert ~app-layout from string-concatenated HTML to pure sexp tree
- Extract ~app-head component, replace ~app-shell with inline structure
- Convert hamburger SVG from Python HTML constant to ~hamburger sexp component
- Fix cross-domain fragment URLs (events_url, market_url)
- Fix starts-with? primitive to handle nil values
- Fix duplicate admin menu rows on OOB swaps
- Add calendar admin nav links (slots, description)
- Convert slots page from Jinja to sexp rendering
- Disable page caching in development mode
- Backfill migration to clean orphaned container_relations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 12:09:00 +00:00
parent d2f1da4944
commit eda95ec58b
14 changed files with 251 additions and 160 deletions

View File

@@ -30,19 +30,6 @@ from typing import Any
from .jinja_bridge import sexp
# HTML constants used by layout components — kept here to avoid
# s-expression parser issues with embedded quotes in SVG.
HAMBURGER_HTML = (
'<div class="md:hidden bg-stone-200 rounded">'
'<svg class="h-12 w-12 transition-transform group-open/root:hidden block self-start"'
' viewBox="0 0 24 24" fill="none" stroke="currentColor">'
'<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"'
' d="M4 6h16M4 12h16M4 18h16"/></svg>'
'<svg aria-hidden="true" viewBox="0 0 24 24"'
' class="w-12 h-12 rotate-180 transition-transform group-open/root:block hidden self-start">'
'<path d="M6 9l6 6 6-6" fill="currentColor"/></svg></div>'
)
SEARCH_HEADERS_MOBILE = '{"X-Origin":"search-mobile","X-Search":"true"}'
SEARCH_HEADERS_DESKTOP = '{"X-Origin":"search-desktop","X-Search":"true"}'
@@ -88,6 +75,11 @@ async def get_template_context(**kwargs: Any) -> dict[str, Any]:
if key not in ctx:
ctx[key] = val
# Expose request-scoped values that sexp components need
from quart import g
if "rights" not in ctx:
ctx["rights"] = getattr(g, "rights", {})
ctx.update(kwargs)
return ctx