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 ----
(defcomp ~geography/demo-provide-basic ()
(div :class "space-y-2"
(div (~tw :tokens "space-y-2")
(provide "theme" {:primary "violet" :accent "rose"}
(div :class "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 :class "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"
(p :class "text-sm text-stone-600" "Outside provider: no theme context."))))
(div (~tw :tokens "rounded-lg p-3 bg-violet-50 border border-violet-200")
(p (~tw :tokens "text-sm text-violet-800 font-semibold") "Inside provider: theme.primary = violet")
(p (~tw :tokens "text-xs text-stone-500") "Child reads context value without prop threading.")))
(div (~tw :tokens "rounded-lg p-3 bg-stone-50 border border-stone-200")
(p (~tw :tokens "text-sm text-stone-600") "Outside provider: no theme context."))))
(defcomp ~geography/demo-emit-collect ()
(div :class "space-y-2"
(div (~tw :tokens "space-y-2")
(provide "scripts" nil
(div :class "rounded-lg p-3 bg-stone-50 border border-stone-200"
(p :class "text-sm text-stone-700"
(div (~tw :tokens "rounded-lg p-3 bg-stone-50 border border-stone-200")
(p (~tw :tokens "text-sm text-stone-700")
(emit! "scripts" "analytics.js")
(emit! "scripts" "charts.js")
"Page content renders here. Scripts emitted silently."))
(div :class "rounded-lg p-3 bg-violet-50 border border-violet-200"
(p :class "text-sm text-violet-800 font-semibold" "Emitted scripts:")
(ul :class "text-xs text-stone-600 list-disc pl-5"
(div (~tw :tokens "rounded-lg p-3 bg-violet-50 border border-violet-200")
(p (~tw :tokens "text-sm text-violet-800 font-semibold") "Emitted scripts:")
(ul (~tw :tokens "text-xs text-stone-600 list-disc pl-5")
(map (fn (s) (li (code s))) (emitted "scripts")))))))
(defcomp ~geography/demo-spread-mechanism ()
(div :class "space-y-2"
(div (make-spread {:class "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 :class "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"})))
(div (~tw :tokens "space-y-2")
(div (make-spread (~tw :tokens "rounded-lg p-3 bg-rose-50 border border-rose-200"))
(p (~tw :tokens "text-sm text-rose-800 font-semibold") "Spread child styled this div")
(p (~tw :tokens "text-xs text-stone-500") "The spread emitted into the element-attrs provider."))
(let ((card (make-spread (~tw :tokens "rounded-lg p-3 bg-amber-50 border border-amber-200"))))
(div card
(p :class "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-sm text-amber-800 font-semibold") "Stored spread, same mechanism")
(p (~tw :tokens "text-xs text-stone-500") "Bound to a let variable, applied when rendered as child.")))))
(defcomp ~geography/demo-nested-provide ()
(div :class "space-y-2"
(div (~tw :tokens "space-y-2")
(provide "level" "outer"
(div :class "rounded-lg p-3 bg-stone-50 border border-stone-200"
(p :class "text-sm text-stone-700"
(div (~tw :tokens "rounded-lg p-3 bg-stone-50 border border-stone-200")
(p (~tw :tokens "text-sm text-stone-700")
(str "Level: " (context "level")))
(provide "level" "inner"
(div :class "rounded-lg p-3 bg-violet-50 border border-violet-200 ml-4"
(p :class "text-sm text-violet-700"
(div (~tw :tokens "rounded-lg p-3 bg-violet-50 border border-violet-200 ml-4")
(p (~tw :tokens "text-sm text-violet-700")
(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")))))))
;; ---- Layout helper (reuse from spreads article) ----
(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 :class "border border-dashed border-stone-300 rounded-lg p-4 bg-stone-50 min-h-[80px]"
(div (~tw :tokens "grid grid-cols-1 lg:grid-cols-2 gap-4 my-6 items-start")
(div (~tw :tokens "border border-dashed border-stone-300 rounded-lg p-4 bg-stone-50 min-h-[80px]")
demo)
(div :class "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)))))
(div (~tw :tokens "not-prose bg-stone-100 rounded-lg p-4 overflow-x-auto")
(pre (~tw :tokens "text-sm leading-relaxed whitespace-pre-wrap break-words") (code code)))))
;; ---- Page content ----
@@ -66,12 +66,12 @@
(defcomp ~geography/provide-content ()
(~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 "
"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. "
"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.")
;; =====================================================================
@@ -190,7 +190,7 @@
"surgically updates attributes when signals change. The static path uses provide/emit!; "
"the reactive path wraps it in an effect.")
(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.")))
;; =====================================================================
@@ -232,19 +232,19 @@
(list "emitted(name)" "Return accumulated values from nearest scope")))
(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, "
"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.")
(~docs/note
(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 "
(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 "
(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 "
(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")
".")))))