sx-headers attributes now use native SX dict format {:key val} instead of
JSON strings. Eliminates manual JSON string construction in both .sx files
and Python callers.
- sx.js: parse sx-headers/sx-vals as SX dict ({: prefix) with JSON fallback,
add _serializeDict for dict→attribute serialization, fix verbInfo scope in
_doFetch error handler
- html.py: serialize dict attribute values via SX serialize() not str()
- All .sx files: {:X-CSRFToken csrf} replaces (str "{\"X-CSRFToken\": ...}")
- All Python callers: {"X-CSRFToken": csrf} dict replaces f-string JSON
- Blog like: extract ~blog-like-toggle, fix POST returning wrong component,
fix emoji escapes in .sx (parser has no \U support), fix card :hx-headers
keyword mismatch, wrap sx_content in SxExpr for evaluation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(filter (feTurbulence ...)) inside (svg ...) has no keyword first arg,
so the keyword-only check dispatched it as a HO function. Now also
check SVG/MathML context (ns in client, _svg_context in server).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Hyphenated names like app-url are variables, not custom elements.
Only treat as custom element when first arg is a Keyword (tag call pattern).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix filter/map dispatching as HO functions when used as SVG/HTML tags
(peek at first arg — Keyword means tag call, not function call)
- Add html: prefix escape hatch to force any name to render as an element
- Support custom elements (hyphenated names) per Web Components spec
- SVG/MathML namespace auto-detection: client threads ns param through
render chain; server uses _svg_context ContextVar so unknown tags
inside (svg ...) or (math ...) render as elements without enumeration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Soviet constructivist poster with paper texture filters, grid lines,
aged stain spots, and "(<x>)" symbol in red.
Add missing SVG filter primitive tags to both server (html.py) and
client (sx.js): feTurbulence, feColorMatrix, feBlend,
feComponentTransfer, feFuncR/G/B/A, feDisplacementMap, feComposite,
feFlood, feImage, feMorphology, feSpecularLighting, feDiffuseLighting,
fePointLight, feSpotLight, feDistantLight.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace Tailwind class strings with native SX expressions:
(css :flex :gap-4 :hover:bg-sky-200) instead of :class "flex gap-4 ..."
- Add style_dict.py: 516 atoms, variants, breakpoints, keyframes, patterns
- Add style_resolver.py: memoized resolver with variant splitting
- Add StyleValue type to types.py (frozen dataclass with class_name, declarations, etc.)
- Add css and merge-styles primitives to primitives.py
- Add defstyle and defkeyframes special forms to evaluator.py and async_eval.py
- Integrate StyleValue into html.py and async_eval.py render paths
- Add register_generated_rule() to css_registry.py, fix media query selector
- Add style dict JSON delivery with localStorage caching to helpers.py
- Add client-side css primitive, resolver, and style injection to sx.js
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Evaluator: add _Thunk + _trampoline for tail-call optimization in
lambdas, components, if/when/cond/case/let/begin. All callers in
html.py, resolver.py, handlers.py, pages.py, jinja_bridge.py, and
query_registry.py unwrap thunks at non-tail positions.
SX docs: update tagline to "s-expressions for the web", rewrite intro
to reflect that SX replaces most JavaScript need, fix "What sx is not"
to acknowledge macros and TCO exist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- 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>
Rename all sexp directories, files, identifiers, and references to sx.
artdag/ excluded (separate media processing DSL).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>