Fix missing SxExpr wraps in events + pretty-print sx in dev mode + multi-expr render
- Wrap 15 call sites in events/sx_components.py where sx-generating functions were passed as plain strings to sx_call(), causing raw s-expression source to leak into the rendered page. - Add dev-mode pretty-printing (RELOAD=true) for sx responses and full page sx source — indented output in Network tab and View Source. - Fix Sx.render to handle multiple top-level expressions by falling back to parseAll and returning a DocumentFragment. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -791,7 +791,7 @@ def _tickets_main_panel_html(ctx: dict, tickets: list) -> str:
|
||||
type_name=tt.name if tt else None,
|
||||
time_str=time_str or None,
|
||||
cal_name=cal.name if cal else None,
|
||||
badge=_ticket_state_badge_html(state),
|
||||
badge=SxExpr(_ticket_state_badge_html(state)),
|
||||
code_prefix=ticket.code[:8]))
|
||||
|
||||
cards_html = "".join(ticket_cards)
|
||||
@@ -904,7 +904,7 @@ def _ticket_admin_main_panel_html(ctx: dict, tickets: list, stats: dict) -> str:
|
||||
entry_name=entry.name if entry else "\u2014",
|
||||
date=SxExpr(date_html),
|
||||
type_name=tt.name if tt else "\u2014",
|
||||
badge=_ticket_state_badge_html(state),
|
||||
badge=SxExpr(_ticket_state_badge_html(state)),
|
||||
action=SxExpr(action_html))
|
||||
|
||||
return sx_call("events-ticket-admin-panel",
|
||||
@@ -973,7 +973,7 @@ def _entry_card_html(entry, page_info: dict, pending_tickets: dict,
|
||||
if tp is not None:
|
||||
qty = pending_tickets.get(entry.id, 0)
|
||||
widget_html = sx_call("events-entry-widget-wrapper",
|
||||
widget=_ticket_widget_html(entry, qty, ticket_url, ctx={}))
|
||||
widget=SxExpr(_ticket_widget_html(entry, qty, ticket_url, ctx={})))
|
||||
|
||||
return sx_call("events-entry-card",
|
||||
title=SxExpr(title_html), badges=SxExpr(badges_html),
|
||||
@@ -1036,7 +1036,7 @@ def _entry_card_tile_html(entry, page_info: dict, pending_tickets: dict,
|
||||
if tp is not None:
|
||||
qty = pending_tickets.get(entry.id, 0)
|
||||
widget_html = sx_call("events-entry-tile-widget-wrapper",
|
||||
widget=_ticket_widget_html(entry, qty, ticket_url, ctx={}))
|
||||
widget=SxExpr(_ticket_widget_html(entry, qty, ticket_url, ctx={})))
|
||||
|
||||
return sx_call("events-entry-card-tile",
|
||||
title=SxExpr(title_html), badges=SxExpr(badges_html),
|
||||
@@ -1154,7 +1154,7 @@ def _view_toggle_html(ctx: dict, view: str) -> str:
|
||||
list_href=list_href, tile_href=tile_href,
|
||||
hx_select=hx_select, list_cls=list_active,
|
||||
tile_cls=tile_active, storage_key="events_view",
|
||||
list_svg=_get_list_svg(), tile_svg=_get_tile_svg())
|
||||
list_svg=SxExpr(_get_list_svg()), tile_svg=SxExpr(_get_tile_svg()))
|
||||
|
||||
|
||||
def _events_main_panel_html(ctx: dict, entries, has_more, pending_tickets, page_info,
|
||||
@@ -1619,7 +1619,7 @@ def render_checkin_result(success: bool, error: str | None, ticket) -> str:
|
||||
entry_name=entry.name if entry else "\u2014",
|
||||
date=SxExpr(date_html),
|
||||
type_name=tt.name if tt else "\u2014",
|
||||
badge=_ticket_state_badge_html("checked_in"),
|
||||
badge=SxExpr(_ticket_state_badge_html("checked_in")),
|
||||
time_str=time_str)
|
||||
|
||||
|
||||
@@ -1656,7 +1656,7 @@ def render_lookup_result(ticket, error: str | None) -> str:
|
||||
if cal:
|
||||
info_html += sx_call("events-lookup-cal", cal_name=cal.name)
|
||||
info_html += sx_call("events-lookup-status",
|
||||
badge=_ticket_state_badge_html(state), code=code)
|
||||
badge=SxExpr(_ticket_state_badge_html(state)), code=code)
|
||||
if checked_in_at:
|
||||
info_html += sx_call("events-lookup-checkin-time",
|
||||
date_str=checked_in_at.strftime("%B %d, %Y at %H:%M"))
|
||||
@@ -1709,7 +1709,7 @@ def render_entry_tickets_admin(entry, tickets: list) -> str:
|
||||
rows_html += sx_call("events-entry-tickets-admin-row",
|
||||
code=code, code_short=code[:12] + "...",
|
||||
type_name=tt.name if tt else "\u2014",
|
||||
badge=_ticket_state_badge_html(state),
|
||||
badge=SxExpr(_ticket_state_badge_html(state)),
|
||||
action=SxExpr(action_html))
|
||||
|
||||
if tickets:
|
||||
@@ -1783,7 +1783,7 @@ def _entry_main_panel_html(ctx: dict) -> str:
|
||||
# State
|
||||
state_html = _field("State", sx_call("events-entry-state-field",
|
||||
entry_id=str(eid),
|
||||
badge=_entry_state_badge_html(state)))
|
||||
badge=SxExpr(_entry_state_badge_html(state))))
|
||||
|
||||
# Cost
|
||||
cost = getattr(entry, "cost", None)
|
||||
@@ -1794,7 +1794,7 @@ def _entry_main_panel_html(ctx: dict) -> str:
|
||||
# Ticket Configuration (admin)
|
||||
tickets_html = _field("Tickets", sx_call("events-entry-tickets-field",
|
||||
entry_id=str(eid),
|
||||
tickets_config=render_entry_tickets_config(entry, calendar, day, month, year)))
|
||||
tickets_config=SxExpr(render_entry_tickets_config(entry, calendar, day, month, year))))
|
||||
|
||||
# Buy Tickets (public-facing)
|
||||
ticket_remaining = ctx.get("ticket_remaining")
|
||||
@@ -1814,7 +1814,7 @@ def _entry_main_panel_html(ctx: dict) -> str:
|
||||
entry_posts = ctx.get("entry_posts") or []
|
||||
posts_html = _field("Associated Posts", sx_call("events-entry-posts-field",
|
||||
entry_id=str(eid),
|
||||
posts_panel=render_entry_posts_panel(entry_posts, entry, calendar, day, month, year)))
|
||||
posts_panel=SxExpr(render_entry_posts_panel(entry_posts, entry, calendar, day, month, year))))
|
||||
|
||||
# Options and Edit Button
|
||||
edit_url = url_for(
|
||||
@@ -1830,7 +1830,7 @@ def _entry_main_panel_html(ctx: dict) -> str:
|
||||
cost=SxExpr(cost_html), tickets=SxExpr(tickets_html),
|
||||
buy=SxExpr(buy_html), date=SxExpr(date_html),
|
||||
posts=SxExpr(posts_html),
|
||||
options=_entry_options_html(entry, calendar, day, month, year),
|
||||
options=SxExpr(_entry_options_html(entry, calendar, day, month, year)),
|
||||
pre_action=pre_action, edit_url=edit_url)
|
||||
|
||||
|
||||
@@ -1861,8 +1861,8 @@ def _entry_header_html(ctx: dict, *, oob: bool = False) -> str:
|
||||
)
|
||||
label_html = sx_call("events-entry-label",
|
||||
entry_id=str(entry.id),
|
||||
title=_entry_title_html(entry),
|
||||
times=_entry_times_html(entry))
|
||||
title=SxExpr(_entry_title_html(entry)),
|
||||
times=SxExpr(_entry_times_html(entry)))
|
||||
|
||||
nav_html = _entry_nav_html(ctx)
|
||||
|
||||
@@ -1988,7 +1988,7 @@ def _entry_title_html(entry) -> str:
|
||||
state = getattr(entry, "state", "pending") or "pending"
|
||||
return sx_call("events-entry-title",
|
||||
name=entry.name,
|
||||
badge=_entry_state_badge_html(state))
|
||||
badge=SxExpr(_entry_state_badge_html(state)))
|
||||
|
||||
|
||||
def _entry_options_html(entry, calendar, day, month, year) -> str:
|
||||
@@ -2578,13 +2578,13 @@ def render_buy_form(entry, ticket_remaining, ticket_sold_count,
|
||||
cost_str = f"\u00a3{tt.cost:.2f}" if tt.cost is not None else "\u00a30.00"
|
||||
type_items += sx_call("events-buy-type-item",
|
||||
type_name=tt.name, cost_str=cost_str,
|
||||
adjust_controls=_ticket_adjust_controls(csrf, adjust_url, target, eid, type_count, ticket_type_id=tt.id))
|
||||
adjust_controls=SxExpr(_ticket_adjust_controls(csrf, adjust_url, target, eid, type_count, ticket_type_id=tt.id)))
|
||||
body_html = sx_call("events-buy-types-wrapper", items=SxExpr(type_items))
|
||||
else:
|
||||
qty = user_ticket_count or 0
|
||||
body_html = sx_call("events-buy-default",
|
||||
price_str=f"\u00a3{tp:.2f}",
|
||||
adjust_controls=_ticket_adjust_controls(csrf, adjust_url, target, eid, qty))
|
||||
adjust_controls=SxExpr(_ticket_adjust_controls(csrf, adjust_url, target, eid, qty)))
|
||||
|
||||
return sx_call("events-buy-panel",
|
||||
entry_id=eid_s, info=SxExpr(info_html), body=SxExpr(body_html))
|
||||
@@ -3491,7 +3491,7 @@ def render_fragment_account_tickets(tickets) -> str:
|
||||
items_html += sx_call("events-frag-ticket-item",
|
||||
href=href, entry_name=ticket.entry_name,
|
||||
date_str=date_str, calendar_name=cal_name,
|
||||
type_name=type_name, badge=badge_html)
|
||||
type_name=type_name, badge=SxExpr(badge_html))
|
||||
body = sx_call("events-frag-tickets-list", items=SxExpr(items_html))
|
||||
else:
|
||||
body = sx_call("empty-state", message="No tickets yet.",
|
||||
@@ -3526,7 +3526,7 @@ def render_fragment_account_bookings(bookings) -> str:
|
||||
name=booking.name,
|
||||
date_str=date_str + date_str_extra,
|
||||
calendar_name=cal_name, cost_str=cost_str,
|
||||
badge=badge_html)
|
||||
badge=SxExpr(badge_html))
|
||||
body = sx_call("events-frag-bookings-list", items=SxExpr(items_html))
|
||||
else:
|
||||
body = sx_call("empty-state", message="No bookings yet.",
|
||||
|
||||
Reference in New Issue
Block a user