Add on-demand CSS: registry, pre-computed component classes, header compression
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 42s
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 42s
- Parse tw.css into per-class lookup registry at startup
- Pre-scan component CSS classes at registration time (avoid per-request regex)
- Compress SX-Css header: 8-char hash replaces full class list (LRU cache)
- Add ;@css comment annotation for dynamically constructed class names
- Safelist bg-sky-{100..400} in Tailwind config for menu-row-sx dynamic shades
- Client sends/receives hash, falls back gracefully on cache miss
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -113,11 +113,25 @@ def register_components(sx_source: str) -> None:
|
||||
"""
|
||||
from .evaluator import _eval
|
||||
from .parser import parse_all
|
||||
from .css_registry import scan_classes_from_sx
|
||||
|
||||
# Snapshot existing component names before eval
|
||||
existing = set(_COMPONENT_ENV.keys())
|
||||
|
||||
exprs = parse_all(sx_source)
|
||||
for expr in exprs:
|
||||
_eval(expr, _COMPONENT_ENV)
|
||||
|
||||
# Pre-scan CSS classes for newly registered components.
|
||||
# Scan the full source once — components from the same file share the set.
|
||||
# Slightly over-counts per component but safe and avoids re-scanning at request time.
|
||||
all_classes: set[str] | None = None
|
||||
for key, val in _COMPONENT_ENV.items():
|
||||
if key not in existing and isinstance(val, Component):
|
||||
if all_classes is None:
|
||||
all_classes = scan_classes_from_sx(sx_source)
|
||||
val.css_classes = set(all_classes)
|
||||
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# sx() — render s-expression from Jinja template
|
||||
@@ -232,6 +246,12 @@ def client_components_tag(*names: str) -> str:
|
||||
return f'<script type="text/sx" data-components>{source}</script>'
|
||||
|
||||
|
||||
def sx_css_all() -> str:
|
||||
"""Return all CSS rules (preamble + utilities) for Jinja fallback pages."""
|
||||
from .css_registry import get_all_css
|
||||
return get_all_css()
|
||||
|
||||
|
||||
def setup_sx_bridge(app: Any) -> None:
|
||||
"""Register s-expression helpers with a Quart app's Jinja environment.
|
||||
|
||||
@@ -243,7 +263,9 @@ def setup_sx_bridge(app: Any) -> None:
|
||||
This registers:
|
||||
- ``sx(source, **kwargs)`` — sync render (components, pure HTML)
|
||||
- ``sx_async(source, **kwargs)`` — async render (with I/O resolution)
|
||||
- ``sx_css_all()`` — full CSS dump for non-sx pages
|
||||
"""
|
||||
app.jinja_env.globals["sx"] = sx
|
||||
app.jinja_env.globals["render"] = render
|
||||
app.jinja_env.globals["sx_async"] = sx_async
|
||||
app.jinja_env.globals["sx_css_all"] = sx_css_all
|
||||
|
||||
Reference in New Issue
Block a user