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:
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)
|
||||
Reference in New Issue
Block a user