All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 1m38s
Layout components now self-resolve context (cart-mini, auth-menu, nav-tree, rights, URLs) via new IO primitives (root-header-ctx, select-colours, account-nav-ctx, app-rights) and defmacro wrappers (~root-header-auto, ~auth-header-row-auto, ~root-mobile-auto). This eliminates _ctx_to_env(), HELPER_CSS_CLASSES, and verbose :key threading across all 10 services. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
82 lines
3.1 KiB
Python
82 lines
3.1 KiB
Python
"""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."""
|
|
from shared.sx.helpers import sx_call
|
|
return sx_call("doc-placeholder", id=div_id)
|
|
|
|
|
|
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."""
|
|
from shared.sx.helpers import sx_call
|
|
return sx_call("doc-oob-code", target_id=target_id, text=text)
|
|
|
|
|
|
def _clear_components_btn() -> str:
|
|
"""Button that clears the client-side component cache (localStorage + in-memory)."""
|
|
from shared.sx.helpers import sx_call
|
|
return sx_call("doc-clear-cache-btn")
|
|
|
|
|
|
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)
|