Update reference SX spec to match sx.js macros branch (CSSX, dict literals, new primitives)
- eval.sx: Add defstyle, defkeyframes, defhandler special forms; add ho-for-each
- parser.sx: Add dict {...} literal parsing and quasiquote/unquote sugar
- primitives.sx: Add parse-datetime, split-ids, css, merge-styles primitives
- render.sx: Add StyleValue handling, SVG filter elements, definition forms in render, fix render-to-html to handle HTML tags directly
- bootstrap_js.py: Add StyleValue type, buildKeyframes, isEvery platform helper, new primitives (format-date, parse-datetime, split-ids, css, merge-styles), dict/quasiquote parser, expose render functions as primitives
- sx-ref.js: Regenerated — 132/132 tests passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -44,10 +44,15 @@
|
||||
;; Media
|
||||
"img" "video" "audio" "source" "picture" "canvas" "iframe"
|
||||
;; SVG
|
||||
"svg" "path" "circle" "rect" "line" "polyline" "polygon" "text"
|
||||
"g" "defs" "use" "clipPath" "mask" "pattern" "linearGradient"
|
||||
"radialGradient" "stop" "filter" "feGaussianBlur" "feOffset"
|
||||
"feBlend" "feColorMatrix" "feComposite" "feMerge" "feMergeNode"
|
||||
"svg" "math" "path" "circle" "ellipse" "rect" "line" "polyline" "polygon"
|
||||
"text" "tspan" "g" "defs" "use" "clipPath" "mask" "pattern"
|
||||
"linearGradient" "radialGradient" "stop" "filter"
|
||||
"feGaussianBlur" "feOffset" "feBlend" "feColorMatrix" "feComposite"
|
||||
"feMerge" "feMergeNode" "feTurbulence"
|
||||
"feComponentTransfer" "feFuncR" "feFuncG" "feFuncB" "feFuncA"
|
||||
"feDisplacementMap" "feFlood" "feImage" "feMorphology"
|
||||
"feSpecularLighting" "feDiffuseLighting"
|
||||
"fePointLight" "feSpotLight" "feDistantLight"
|
||||
"animate" "animateTransform" "foreignObject"
|
||||
;; Other
|
||||
"template" "slot" "dialog" "menu"))
|
||||
@@ -57,9 +62,10 @@
|
||||
"link" "meta" "param" "source" "track" "wbr"))
|
||||
|
||||
(define BOOLEAN_ATTRS
|
||||
(list "disabled" "checked" "selected" "readonly" "required" "hidden"
|
||||
"autofocus" "autoplay" "controls" "loop" "muted" "defer" "async"
|
||||
"novalidate" "formnovalidate" "multiple" "open" "allowfullscreen"))
|
||||
(list "async" "autofocus" "autoplay" "checked" "controls" "default"
|
||||
"defer" "disabled" "formnovalidate" "hidden" "inert" "ismap"
|
||||
"loop" "multiple" "muted" "nomodule" "novalidate" "open"
|
||||
"playsinline" "readonly" "required" "reversed" "selected"))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -68,8 +74,20 @@
|
||||
|
||||
(define render-to-html
|
||||
(fn (expr env)
|
||||
(let ((result (trampoline (eval-expr expr env))))
|
||||
(render-value-to-html result env))))
|
||||
(case (type-of expr)
|
||||
;; Literals — render directly
|
||||
"nil" ""
|
||||
"string" (escape-html expr)
|
||||
"number" (str expr)
|
||||
"boolean" (if expr "true" "false")
|
||||
;; List — dispatch to render-list which handles HTML tags, special forms, etc.
|
||||
"list" (if (empty? expr) "" (render-list-to-html expr env))
|
||||
;; Symbol — evaluate then render
|
||||
"symbol" (render-value-to-html (trampoline (eval-expr expr env)) env)
|
||||
;; Keyword — render as text
|
||||
"keyword" (escape-html (keyword-name expr))
|
||||
;; Everything else — evaluate first
|
||||
:else (render-value-to-html (trampoline (eval-expr expr env)) env))))
|
||||
|
||||
(define render-value-to-html
|
||||
(fn (val env)
|
||||
@@ -80,6 +98,7 @@
|
||||
"boolean" (if val "true" "false")
|
||||
"list" (render-list-to-html val env)
|
||||
"raw-html" (raw-html-content val)
|
||||
"style-value" (style-value-class val)
|
||||
:else (escape-html (str val)))))
|
||||
|
||||
(define render-list-to-html
|
||||
@@ -114,6 +133,11 @@
|
||||
env)
|
||||
(error (str "Unknown component: " name))))
|
||||
|
||||
;; Definitions — evaluate for side effects, render nothing
|
||||
(or (= name "define") (= name "defcomp") (= name "defmacro")
|
||||
(= name "defstyle") (= name "defkeyframes") (= name "defhandler"))
|
||||
(do (trampoline (eval-expr expr env)) "")
|
||||
|
||||
;; Macro expansion
|
||||
(and (env-has? env name) (macro? (env-get env name)))
|
||||
(render-to-html
|
||||
@@ -182,6 +206,9 @@
|
||||
""
|
||||
;; Nil values — skip
|
||||
(nil? val) ""
|
||||
;; StyleValue on :style → emit as class
|
||||
(and (= key "style") (style-value? val))
|
||||
(str " class=\"" (style-value-class val) "\"")
|
||||
;; Normal attr
|
||||
:else (str " " key "=\"" (escape-attr (str val)) "\""))))
|
||||
(keys attrs)))))
|
||||
@@ -323,6 +350,10 @@
|
||||
;; (set-attribute el k v) → void
|
||||
;; (append-child parent c) → void
|
||||
;;
|
||||
;; StyleValue:
|
||||
;; (style-value? x) → boolean (is x a StyleValue?)
|
||||
;; (style-value-class sv) → string (CSS class name)
|
||||
;;
|
||||
;; Serialization:
|
||||
;; (serialize val) → SX source string representation of val
|
||||
;;
|
||||
|
||||
Reference in New Issue
Block a user