Fix provide.sx parse error: dict literal can't have component call as key

{(~tw ...)} is invalid — dict keys must be keywords/strings/symbols.
Changed to (make-spread (~tw ...)) which evaluates the component first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-02 11:25:03 +00:00
parent 8ab7e367d8
commit 9ed1100ef6

View File

@@ -6,59 +6,59 @@
;; ---- Demo components ---- ;; ---- Demo components ----
(defcomp ~geography/demo-provide-basic () (defcomp ~geography/demo-provide-basic ()
(div :class "space-y-2" (div (~tw :tokens "space-y-2")
(provide "theme" {:primary "violet" :accent "rose"} (provide "theme" {:primary "violet" :accent "rose"}
(div :class "rounded-lg p-3 bg-violet-50 border border-violet-200" (div (~tw :tokens "rounded-lg p-3 bg-violet-50 border border-violet-200")
(p :class "text-sm text-violet-800 font-semibold" "Inside provider: theme.primary = violet") (p (~tw :tokens "text-sm text-violet-800 font-semibold") "Inside provider: theme.primary = violet")
(p :class "text-xs text-stone-500" "Child reads context value without prop threading."))) (p (~tw :tokens "text-xs text-stone-500") "Child reads context value without prop threading.")))
(div :class "rounded-lg p-3 bg-stone-50 border border-stone-200" (div (~tw :tokens "rounded-lg p-3 bg-stone-50 border border-stone-200")
(p :class "text-sm text-stone-600" "Outside provider: no theme context.")))) (p (~tw :tokens "text-sm text-stone-600") "Outside provider: no theme context."))))
(defcomp ~geography/demo-emit-collect () (defcomp ~geography/demo-emit-collect ()
(div :class "space-y-2" (div (~tw :tokens "space-y-2")
(provide "scripts" nil (provide "scripts" nil
(div :class "rounded-lg p-3 bg-stone-50 border border-stone-200" (div (~tw :tokens "rounded-lg p-3 bg-stone-50 border border-stone-200")
(p :class "text-sm text-stone-700" (p (~tw :tokens "text-sm text-stone-700")
(emit! "scripts" "analytics.js") (emit! "scripts" "analytics.js")
(emit! "scripts" "charts.js") (emit! "scripts" "charts.js")
"Page content renders here. Scripts emitted silently.")) "Page content renders here. Scripts emitted silently."))
(div :class "rounded-lg p-3 bg-violet-50 border border-violet-200" (div (~tw :tokens "rounded-lg p-3 bg-violet-50 border border-violet-200")
(p :class "text-sm text-violet-800 font-semibold" "Emitted scripts:") (p (~tw :tokens "text-sm text-violet-800 font-semibold") "Emitted scripts:")
(ul :class "text-xs text-stone-600 list-disc pl-5" (ul (~tw :tokens "text-xs text-stone-600 list-disc pl-5")
(map (fn (s) (li (code s))) (emitted "scripts"))))))) (map (fn (s) (li (code s))) (emitted "scripts")))))))
(defcomp ~geography/demo-spread-mechanism () (defcomp ~geography/demo-spread-mechanism ()
(div :class "space-y-2" (div (~tw :tokens "space-y-2")
(div (make-spread {:class "rounded-lg p-3 bg-rose-50 border border-rose-200"}) (div (make-spread (~tw :tokens "rounded-lg p-3 bg-rose-50 border border-rose-200"))
(p :class "text-sm text-rose-800 font-semibold" "Spread child styled this div") (p (~tw :tokens "text-sm text-rose-800 font-semibold") "Spread child styled this div")
(p :class "text-xs text-stone-500" "The spread emitted into the element-attrs provider.")) (p (~tw :tokens "text-xs text-stone-500") "The spread emitted into the element-attrs provider."))
(let ((card (make-spread {:class "rounded-lg p-3 bg-amber-50 border border-amber-200"}))) (let ((card (make-spread (~tw :tokens "rounded-lg p-3 bg-amber-50 border border-amber-200"))))
(div card (div card
(p :class "text-sm text-amber-800 font-semibold" "Stored spread, same mechanism") (p (~tw :tokens "text-sm text-amber-800 font-semibold") "Stored spread, same mechanism")
(p :class "text-xs text-stone-500" "Bound to a let variable, applied when rendered as child."))))) (p (~tw :tokens "text-xs text-stone-500") "Bound to a let variable, applied when rendered as child.")))))
(defcomp ~geography/demo-nested-provide () (defcomp ~geography/demo-nested-provide ()
(div :class "space-y-2" (div (~tw :tokens "space-y-2")
(provide "level" "outer" (provide "level" "outer"
(div :class "rounded-lg p-3 bg-stone-50 border border-stone-200" (div (~tw :tokens "rounded-lg p-3 bg-stone-50 border border-stone-200")
(p :class "text-sm text-stone-700" (p (~tw :tokens "text-sm text-stone-700")
(str "Level: " (context "level"))) (str "Level: " (context "level")))
(provide "level" "inner" (provide "level" "inner"
(div :class "rounded-lg p-3 bg-violet-50 border border-violet-200 ml-4" (div (~tw :tokens "rounded-lg p-3 bg-violet-50 border border-violet-200 ml-4")
(p :class "text-sm text-violet-700" (p (~tw :tokens "text-sm text-violet-700")
(str "Level: " (context "level"))))) (str "Level: " (context "level")))))
(p :class "text-sm text-stone-500 mt-1" (p (~tw :tokens "text-sm text-stone-500 mt-1")
(str "Back to: " (context "level"))))))) (str "Back to: " (context "level")))))))
;; ---- Layout helper (reuse from spreads article) ---- ;; ---- Layout helper (reuse from spreads article) ----
(defcomp ~geography/provide-demo-example (&key demo code) (defcomp ~geography/provide-demo-example (&key demo code)
(div :class "grid grid-cols-1 lg:grid-cols-2 gap-4 my-6 items-start" (div (~tw :tokens "grid grid-cols-1 lg:grid-cols-2 gap-4 my-6 items-start")
(div :class "border border-dashed border-stone-300 rounded-lg p-4 bg-stone-50 min-h-[80px]" (div (~tw :tokens "border border-dashed border-stone-300 rounded-lg p-4 bg-stone-50 min-h-[80px]")
demo) demo)
(div :class "not-prose bg-stone-100 rounded-lg p-4 overflow-x-auto" (div (~tw :tokens "not-prose bg-stone-100 rounded-lg p-4 overflow-x-auto")
(pre :class "text-sm leading-relaxed whitespace-pre-wrap break-words" (code code))))) (pre (~tw :tokens "text-sm leading-relaxed whitespace-pre-wrap break-words") (code code)))))
;; ---- Page content ---- ;; ---- Page content ----
@@ -66,12 +66,12 @@
(defcomp ~geography/provide-content () (defcomp ~geography/provide-content ()
(~docs/page :title "Provide / Context / Emit!" (~docs/page :title "Provide / Context / Emit!"
(p :class "text-stone-500 text-sm italic mb-8" (p (~tw :tokens "text-stone-500 text-sm italic mb-8")
"Sugar for " (code "scope") " with a value. " (code "provide") " creates a named scope " "Sugar for " (code "scope") " with a value. " (code "provide") " creates a named scope "
"with a value and an accumulator. " (code "context") " reads the value downward. " "with a value and an accumulator. " (code "context") " reads the value downward. "
(code "emit!") " appends to the accumulator upward. " (code "emitted") " retrieves what was emitted. " (code "emit!") " appends to the accumulator upward. " (code "emitted") " retrieves what was emitted. "
"See " "See "
(a :href "/sx/(geography.(scopes))" :class "text-violet-600 hover:underline" "scopes") (a :href "/sx/(geography.(scopes))" (~tw :tokens "text-violet-600 hover:underline") "scopes")
" for the unified primitive.") " for the unified primitive.")
;; ===================================================================== ;; =====================================================================
@@ -190,7 +190,7 @@
"surgically updates attributes when signals change. The static path uses provide/emit!; " "surgically updates attributes when signals change. The static path uses provide/emit!; "
"the reactive path wraps it in an effect.") "the reactive path wraps it in an effect.")
(p "See the " (p "See the "
(a :href "/sx/(geography.(spreads))" :class "text-violet-600 hover:underline" "spreads article") (a :href "/sx/(geography.(spreads))" (~tw :tokens "text-violet-600 hover:underline") "spreads article")
" for reactive-spread details."))) " for reactive-spread details.")))
;; ===================================================================== ;; =====================================================================
@@ -232,19 +232,19 @@
(list "emitted(name)" "Return accumulated values from nearest scope"))) (list "emitted(name)" "Return accumulated values from nearest scope")))
(p (code "provide") " is a special form in " (p (code "provide") " is a special form in "
(a :href "/sx/(language.(spec.(explore.evaluator)))" :class "font-mono text-violet-600 hover:underline text-sm" "eval.sx") (a :href "/sx/(language.(spec.(explore.evaluator)))" (~tw :tokens "font-mono text-violet-600 hover:underline text-sm") "eval.sx")
" — it calls " (code "scope-push!") ", evaluates the body, " " — it calls " (code "scope-push!") ", evaluates the body, "
"then calls " (code "scope-pop!") ". See " "then calls " (code "scope-pop!") ". See "
(a :href "/sx/(geography.(scopes))" :class "text-violet-600 hover:underline" "scopes") (a :href "/sx/(geography.(scopes))" (~tw :tokens "text-violet-600 hover:underline") "scopes")
" for the full unified platform.") " for the full unified platform.")
(~docs/note (~docs/note
(p (strong "Spec explorer: ") "See the provide/emit! primitives in " (p (strong "Spec explorer: ") "See the provide/emit! primitives in "
(a :href "/sx/(language.(spec.(explore.boundary)))" :class "font-mono text-violet-600 hover:underline text-sm" "boundary.sx explorer") (a :href "/sx/(language.(spec.(explore.boundary)))" (~tw :tokens "font-mono text-violet-600 hover:underline text-sm") "boundary.sx explorer")
". The " (code "provide") " special form is in " ". The " (code "provide") " special form is in "
(a :href "/sx/(language.(spec.(explore.evaluator)))" :class "font-mono text-violet-600 hover:underline text-sm" "eval.sx explorer") (a :href "/sx/(language.(spec.(explore.evaluator)))" (~tw :tokens "font-mono text-violet-600 hover:underline text-sm") "eval.sx explorer")
". Element rendering with provide/emit! is visible in " ". Element rendering with provide/emit! is visible in "
(a :href "/sx/(language.(spec.(explore.adapter-html)))" :class "font-mono text-violet-600 hover:underline text-sm" "adapter-html") (a :href "/sx/(language.(spec.(explore.adapter-html)))" (~tw :tokens "font-mono text-violet-600 hover:underline text-sm") "adapter-html")
" and " " and "
(a :href "/sx/(language.(spec.(explore.adapter-async)))" :class "font-mono text-violet-600 hover:underline text-sm" "adapter-async") (a :href "/sx/(language.(spec.(explore.adapter-async)))" (~tw :tokens "font-mono text-violet-600 hover:underline text-sm") "adapter-async")
"."))))) ".")))))