Add syntax highlighting to spreads page code blocks
Use (highlight "..." "lisp") page helper instead of raw strings for ~docs/code :code values. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -22,12 +22,9 @@
|
||||
(p "A spread is a value type. " (code "make-spread") " creates one from a dict of "
|
||||
"attributes. When the renderer encounters a spread as a child of an element, "
|
||||
"it merges the attrs onto the parent element instead of appending a DOM node.")
|
||||
(~docs/code :code "(defcomp ~highlight (&key colour)
|
||||
(make-spread {\"class\" (str \"highlight-\" colour)
|
||||
\"data-highlight\" colour}))")
|
||||
(~docs/code :code (highlight "(defcomp ~highlight (&key colour)\n (make-spread {\"class\" (str \"highlight-\" colour)\n \"data-highlight\" colour}))" "lisp"))
|
||||
(p "Use it as a child of any element:")
|
||||
(~docs/code :code "(div (~highlight :colour \"yellow\")
|
||||
\"This div gets class=highlight-yellow\")")
|
||||
(~docs/code :code (highlight "(div (~highlight :colour \"yellow\")\n \"This div gets class=highlight-yellow\")" "lisp"))
|
||||
(p (code "class") " values are appended (space-joined). "
|
||||
(code "style") " values are appended (semicolon-joined). "
|
||||
"All other attributes overwrite."))
|
||||
@@ -35,13 +32,7 @@
|
||||
(~docs/subsection :title "2. collect! / collected / clear-collected!"
|
||||
(p "Render-time accumulators. Values are collected into named buckets "
|
||||
"during rendering and retrieved at flush points. Deduplication is automatic.")
|
||||
(~docs/code :code ";; Deep inside a component tree:
|
||||
(collect! \"cssx\" \".sx-bg-red-500{background-color:hsl(0,72%,53%)}\")
|
||||
|
||||
;; At the flush point (once, in the layout):
|
||||
(let ((rules (collected \"cssx\")))
|
||||
(clear-collected! \"cssx\")
|
||||
(raw! (str \"<style>\" (join \"\" rules) \"</style>\")))")
|
||||
(~docs/code :code (highlight ";; Deep inside a component tree:\n(collect! \"cssx\" \".sx-bg-red-500{background-color:hsl(0,72%,53%)}\")\n\n;; At the flush point (once, in the layout):\n(let ((rules (collected \"cssx\")))\n (clear-collected! \"cssx\")\n (raw! (str \"<style>\" (join \"\" rules) \"</style>\")))" "lisp"))
|
||||
(p "This is upward communication through the render tree: "
|
||||
"a deeply nested component contributes a CSS rule, and the layout "
|
||||
"emits all accumulated rules as a single " (code "<style>") " tag. "
|
||||
@@ -51,11 +42,7 @@
|
||||
(p "Inside an island, when a spread's value depends on signals, "
|
||||
(code "reactive-spread") " tracks signal dependencies and surgically "
|
||||
"updates the parent element's attributes when signals change.")
|
||||
(~docs/code :code "(defisland ~themed-card ()
|
||||
(let ((theme (signal \"violet\")))
|
||||
(div (~cssx/tw :tokens (str \"bg-\" (deref theme) \"-500 p-4\"))
|
||||
(button :on-click (fn (e) (reset! theme \"rose\"))
|
||||
\"change theme\"))))")
|
||||
(~docs/code :code (highlight "(defisland ~themed-card ()\n (let ((theme (signal \"violet\")))\n (div (~cssx/tw :tokens (str \"bg-\" (deref theme) \"-500 p-4\"))\n (button :on-click (fn (e) (reset! theme \"rose\"))\n \"change theme\"))))" "lisp"))
|
||||
(p "When " (code "theme") " changes from " (code "\"violet\"") " to "
|
||||
(code "\"rose\"") ":")
|
||||
(ul :class "list-disc pl-5 space-y-1 text-stone-600"
|
||||
@@ -111,18 +98,7 @@
|
||||
|
||||
(~docs/section :title "CSSX: the first application" :id "cssx"
|
||||
(p (code "~cssx/tw") " is a component that uses all three primitives:")
|
||||
(~docs/code :code "(defcomp ~cssx/tw (tokens)
|
||||
(let ((token-list (filter (fn (t) (not (= t \"\")))
|
||||
(split (or tokens \"\") \" \")))
|
||||
(results (map cssx-process-token token-list))
|
||||
(valid (filter (fn (r) (not (nil? r))) results))
|
||||
(classes (map (fn (r) (get r \"cls\")) valid))
|
||||
(rules (map (fn (r) (get r \"rule\")) valid))
|
||||
(_ (for-each (fn (rule) (collect! \"cssx\" rule)) rules)))
|
||||
(if (empty? classes)
|
||||
nil
|
||||
(make-spread {\"class\" (join \" \" classes)
|
||||
\"data-tw\" (or tokens \"\")}))))")
|
||||
(~docs/code :code (highlight "(defcomp ~cssx/tw (tokens)\n (let ((token-list (filter (fn (t) (not (= t \"\")))\n (split (or tokens \"\") \" \")))\n (results (map cssx-process-token token-list))\n (valid (filter (fn (r) (not (nil? r))) results))\n (classes (map (fn (r) (get r \"cls\")) valid))\n (rules (map (fn (r) (get r \"rule\")) valid))\n (_ (for-each (fn (rule) (collect! \"cssx\" rule)) rules)))\n (if (empty? classes)\n nil\n (make-spread {\"class\" (join \" \" classes)\n \"data-tw\" (or tokens \"\")}))))" "lisp"))
|
||||
(p "It's a regular " (code "defcomp") ". It uses " (code "make-spread") " to "
|
||||
"inject classes onto its parent, " (code "collect!") " to accumulate CSS rules "
|
||||
"for batch flushing, and when called inside an island with signal-dependent "
|
||||
@@ -141,15 +117,7 @@
|
||||
(~docs/section :title "Semantic style variables" :id "variables"
|
||||
(p "Because " (code "~cssx/tw") " returns a spread, and spreads are values, "
|
||||
"you can bind them to names:")
|
||||
(~docs/code :code ";; Define once
|
||||
(define heading-style (~cssx/tw :tokens \"text-violet-700 text-2xl font-bold\"))
|
||||
(define nav-link (~cssx/tw :tokens \"text-stone-500 text-sm\"))
|
||||
(define card-base (~cssx/tw :tokens \"bg-stone-50 rounded-lg p-4\"))
|
||||
|
||||
;; Use everywhere
|
||||
(div card-base
|
||||
(h1 heading-style \"Title\")
|
||||
(a nav-link :href \"/\" \"Home\"))")
|
||||
(~docs/code :code (highlight ";; Define once\n(define heading-style (~cssx/tw :tokens \"text-violet-700 text-2xl font-bold\"))\n(define nav-link (~cssx/tw :tokens \"text-stone-500 text-sm\"))\n(define card-base (~cssx/tw :tokens \"bg-stone-50 rounded-lg p-4\"))\n\n;; Use everywhere\n(div card-base\n (h1 heading-style \"Title\")\n (a nav-link :href \"/\" \"Home\"))" "lisp"))
|
||||
(p "These are semantic names wrapping utility tokens. Change the definition, "
|
||||
"every use updates. No build step, no CSS-in-JS runtime. Just " (code "define") ".")
|
||||
(p "Namespacing prevents clashes \u2014 " (code "~app/heading") " vs "
|
||||
@@ -194,24 +162,7 @@
|
||||
(p (code "provide") " creates a named scope with a value (downward) and an accumulator (upward). "
|
||||
(code "context") " reads the value. " (code "emit!") " appends to the accumulator. "
|
||||
(code "emitted") " retrieves accumulated values.")
|
||||
(~docs/code :code ";; Downward: theme context
|
||||
(provide \"theme\" {:primary \"violet\" :font \"serif\"}
|
||||
(h1 :style (str \"color:\" (get (context \"theme\") :primary))
|
||||
\"Themed heading\"))
|
||||
|
||||
;; Upward: script accumulation (like collect!)
|
||||
(provide \"scripts\" nil
|
||||
(div
|
||||
(emit! \"scripts\" \"analytics.js\")
|
||||
(div (emit! \"scripts\" \"charts.js\") \"chart\"))
|
||||
(for-each (fn (s) (script :src s)) (emitted \"scripts\")))
|
||||
|
||||
;; Both at once
|
||||
(provide \"page\" {:title \"Home\"}
|
||||
(h1 (context \"page\" :title))
|
||||
(emit! \"page\" {:meta \"og:title\" :content \"Home\"})
|
||||
(for-each (fn (m) (meta :name (get m :meta) :content (get m :content)))
|
||||
(emitted \"page\")))"))
|
||||
(~docs/code :code (highlight ";; Downward: theme context\n(provide \"theme\" {:primary \"violet\" :font \"serif\"}\n (h1 :style (str \"color:\" (get (context \"theme\") :primary))\n \"Themed heading\"))\n\n;; Upward: script accumulation (like collect!)\n(provide \"scripts\" nil\n (div\n (emit! \"scripts\" \"analytics.js\")\n (div (emit! \"scripts\" \"charts.js\") \"chart\"))\n (for-each (fn (s) (script :src s)) (emitted \"scripts\")))\n\n;; Both at once\n(provide \"page\" {:title \"Home\"}\n (h1 (context \"page\" :title))\n (emit! \"page\" {:meta \"og:title\" :content \"Home\"})\n (for-each (fn (m) (meta :name (get m :meta) :content (get m :content)))\n (emitted \"page\")))" "lisp")))
|
||||
|
||||
(~docs/subsection :title "What this means"
|
||||
(p "Three mechanisms collapse into one:")
|
||||
|
||||
Reference in New Issue
Block a user