sx-tools: WASM kernel updates, TW/CSSX rework, content refresh, new debugging tools
Build tooling: updated OCaml bootstrapper, compile-modules, bundle.sh, sx-build-all. WASM browser: rebuilt sx_browser.bc.js/wasm, sx-platform-2.js, .sxbc bytecode files. CSSX/Tailwind: reworked cssx.sx templates and tw-layout, added tw-type support. Content: refreshed essays, plans, geography, reactive islands, docs, demos, handlers. New tools: bisect_sxbc.sh, test-spa.js, render-trace.sx, morph playwright spec. Tests: added test-match.sx, test-examples.sx, updated test-tw.sx and web tests. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -178,13 +178,13 @@
|
||||
(let
|
||||
((now (helper "now" "%H:%M:%S")))
|
||||
(<>
|
||||
(p :class "text-emerald-600 font-medium" "Box A updated!")
|
||||
(p :class "text-sm text-stone-500" (str "at " now))
|
||||
(p (~tw :tokens "text-emerald-600 font-medium") "Box A updated!")
|
||||
(p (~tw :tokens "text-sm text-stone-500") (str "at " now))
|
||||
(div
|
||||
:id "oob-box-b"
|
||||
:sx-swap-oob "innerHTML"
|
||||
(p :class "text-violet-600 font-medium" "Box B updated via OOB!")
|
||||
(p :class "text-sm text-stone-500" (str "at " now)))
|
||||
(p (~tw :tokens "text-violet-600 font-medium") "Box B updated via OOB!")
|
||||
(p (~tw :tokens "text-sm text-stone-500") (str "at " now)))
|
||||
(~docs/oob-code
|
||||
:target-id "oob-wire"
|
||||
:text (str
|
||||
@@ -222,7 +222,7 @@
|
||||
(fn
|
||||
(i)
|
||||
(div
|
||||
:class "px-4 py-3 border-b border-stone-100 text-sm text-stone-700"
|
||||
(~tw :tokens "px-4 py-3 border-b border-stone-100 text-sm text-stone-700")
|
||||
(str "Item " i " — loaded from page " page)))
|
||||
(range start (+ start 5)))
|
||||
(if
|
||||
@@ -235,10 +235,10 @@
|
||||
:sx-trigger "intersect once"
|
||||
:sx-target "#scroll-items"
|
||||
:sx-swap "beforeend"
|
||||
:class "p-3 text-center text-stone-400 text-sm"
|
||||
(~tw :tokens "p-3 text-center text-stone-400 text-sm")
|
||||
"Loading more...")
|
||||
(div
|
||||
:class "p-3 text-center text-stone-500 text-sm font-medium"
|
||||
(~tw :tokens "p-3 text-center text-stone-500 text-sm font-medium")
|
||||
"All items loaded."))
|
||||
(~docs/oob-code
|
||||
:target-id "scroll-wire"
|
||||
@@ -373,9 +373,9 @@
|
||||
((email (helper "request-form" "email" "")))
|
||||
(if
|
||||
(or (= email "") (not (contains? email "@")))
|
||||
(p :class "text-sm text-rose-600 mt-2" "Please enter a valid email.")
|
||||
(p (~tw :tokens "text-sm text-rose-600 mt-2") "Please enter a valid email.")
|
||||
(p
|
||||
:class "text-sm text-emerald-600 mt-2"
|
||||
(~tw :tokens "text-sm text-emerald-600 mt-2")
|
||||
(str "Form submitted with: " email)))))
|
||||
|
||||
(defhandler
|
||||
@@ -536,12 +536,12 @@
|
||||
(helper "state-set!" "ex-swap-n" n)
|
||||
(<>
|
||||
(div
|
||||
:class "px-3 py-2 text-sm text-stone-700"
|
||||
(~tw :tokens "px-3 py-2 text-sm text-stone-700")
|
||||
(str "[" now "] " mode " (#" n ")"))
|
||||
(span
|
||||
:id "swap-counter"
|
||||
:sx-swap-oob "innerHTML"
|
||||
:class "self-center text-sm text-stone-500"
|
||||
(~tw :tokens "self-center text-sm text-stone-500")
|
||||
(str "Count: " n))
|
||||
(~docs/oob-code
|
||||
:target-id "swap-wire"
|
||||
@@ -558,28 +558,28 @@
|
||||
(<>
|
||||
(div
|
||||
:id "dash-header"
|
||||
:class "p-3 bg-violet-50 rounded mb-3"
|
||||
(h4 :class "font-semibold text-violet-800" "Dashboard Header")
|
||||
(p :class "text-sm text-violet-600" (str "Generated at " now)))
|
||||
(~tw :tokens "p-3 bg-violet-50 rounded mb-3")
|
||||
(h4 (~tw :tokens "font-semibold text-violet-800") "Dashboard Header")
|
||||
(p (~tw :tokens "text-sm text-violet-600") (str "Generated at " now)))
|
||||
(div
|
||||
:id "dash-stats"
|
||||
:class "grid grid-cols-3 gap-3 mb-3"
|
||||
(~tw :tokens "grid grid-cols-3 gap-3 mb-3")
|
||||
(div
|
||||
:class "p-3 bg-emerald-50 rounded text-center"
|
||||
(p :class "text-2xl font-bold text-emerald-700" "142")
|
||||
(p :class "text-xs text-emerald-600" "Users"))
|
||||
(~tw :tokens "p-3 bg-emerald-50 rounded text-center")
|
||||
(p (~tw :tokens "text-2xl font-bold text-emerald-700") "142")
|
||||
(p (~tw :tokens "text-xs text-emerald-600") "Users"))
|
||||
(div
|
||||
:class "p-3 bg-blue-50 rounded text-center"
|
||||
(p :class "text-2xl font-bold text-blue-700" "89")
|
||||
(p :class "text-xs text-blue-600" "Orders"))
|
||||
(~tw :tokens "p-3 bg-blue-50 rounded text-center")
|
||||
(p (~tw :tokens "text-2xl font-bold text-blue-700") "89")
|
||||
(p (~tw :tokens "text-xs text-blue-600") "Orders"))
|
||||
(div
|
||||
:class "p-3 bg-amber-50 rounded text-center"
|
||||
(p :class "text-2xl font-bold text-amber-700" "$4.2k")
|
||||
(p :class "text-xs text-amber-600" "Revenue")))
|
||||
(~tw :tokens "p-3 bg-amber-50 rounded text-center")
|
||||
(p (~tw :tokens "text-2xl font-bold text-amber-700") "$4.2k")
|
||||
(p (~tw :tokens "text-xs text-amber-600") "Revenue")))
|
||||
(div
|
||||
:id "dash-footer"
|
||||
:class "p-3 bg-stone-50 rounded"
|
||||
(p :class "text-sm text-stone-500" (str "Last updated: " now)))
|
||||
(~tw :tokens "p-3 bg-stone-50 rounded")
|
||||
(p (~tw :tokens "text-sm text-stone-500") (str "Last updated: " now)))
|
||||
(~docs/oob-code
|
||||
:target-id "filter-wire"
|
||||
:text (str
|
||||
@@ -598,7 +598,7 @@
|
||||
(div
|
||||
:id "tab-buttons"
|
||||
:sx-swap-oob "innerHTML"
|
||||
:class "flex border-b border-stone-200"
|
||||
(~tw :tokens "flex border-b border-stone-200")
|
||||
(~examples/tab-btn
|
||||
:tab "tab1"
|
||||
:label "Overview"
|
||||
|
||||
@@ -45,11 +45,11 @@
|
||||
(filter (fn (item) (string-contains? (lower item) (lower query)))
|
||||
items))))
|
||||
(let ((shown (slice matches 0 3)))
|
||||
(div :class "space-y-1"
|
||||
(div (~tw :tokens "space-y-1")
|
||||
(p :class (str "text-xs font-semibold uppercase " color) label)
|
||||
(ul :class "list-disc pl-4"
|
||||
(map (fn (m) (li :class "text-sm text-stone-600" m)) shown))
|
||||
(p :class "text-xs text-stone-400"
|
||||
(ul (~tw :tokens "list-disc pl-4")
|
||||
(map (fn (m) (li (~tw :tokens "text-sm text-stone-600") m)) shown))
|
||||
(p (~tw :tokens "text-xs text-stone-400")
|
||||
(str (length matches) " result(s)"))))))
|
||||
|
||||
|
||||
@@ -66,10 +66,10 @@
|
||||
(now (helper "now" "%H:%M:%S")))
|
||||
(let ((price (nth flash-sale-prices idx)))
|
||||
(<>
|
||||
(div :class "space-y-2"
|
||||
(p :class "text-sm text-emerald-600 font-medium"
|
||||
(div (~tw :tokens "space-y-2")
|
||||
(p (~tw :tokens "text-sm text-emerald-600 font-medium")
|
||||
(str "⚡ Flash sale! Price: $" price))
|
||||
(p :class "text-xs text-stone-400" (str "at " now)))
|
||||
(p (~tw :tokens "text-xs text-stone-400") (str "at " now)))
|
||||
(script :type "text/sx" :data-init ""
|
||||
(str "(reset! (use-store \"demo-price\") " price ")"))))))
|
||||
|
||||
@@ -86,9 +86,9 @@
|
||||
(let ((idx (random-int 0 (- (length settle-items) 1)))
|
||||
(now (helper "now" "%H:%M:%S")))
|
||||
(let ((item (nth settle-items idx)))
|
||||
(div :class "space-y-1"
|
||||
(p :class "text-sm font-medium text-stone-700" (str "Fetched: " item))
|
||||
(p :class "text-xs text-stone-400" (str "at " now))))))
|
||||
(div (~tw :tokens "space-y-1")
|
||||
(p (~tw :tokens "text-sm font-medium text-stone-700") (str "Fetched: " item))
|
||||
(p (~tw :tokens "text-xs text-stone-400") (str "at " now))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -160,7 +160,7 @@
|
||||
"" rotated)
|
||||
")")))
|
||||
(<>
|
||||
(p :class "text-sm text-emerald-600 font-medium"
|
||||
(p (~tw :tokens "text-sm text-emerald-600 font-medium")
|
||||
(str "Catalog loaded: " (length rotated) " items (shuffled at " now ")"))
|
||||
(script :type "text/sx" :data-init ""
|
||||
(str "(reset! (use-store \"catalog-items\") " items-sx ")")))))))
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
(&key)
|
||||
(let ((now (helper "now" "%H:%M:%S")))
|
||||
(<>
|
||||
(span :class "text-stone-800 text-sm" "Server time: " (strong now))
|
||||
(span (~tw :tokens "text-stone-800 text-sm") "Server time: " (strong now))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-get"
|
||||
:text (str "(span :class \"text-stone-800 text-sm\" \"Server time: \" (strong \"" now "\"))")))))
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
(&key)
|
||||
(let ((name (helper "request-form" "name" "stranger")))
|
||||
(<>
|
||||
(span :class "text-stone-800 text-sm" "Hello, " (strong name) "!")
|
||||
(span (~tw :tokens "text-stone-800 text-sm") "Hello, " (strong name) "!")
|
||||
(~docs/oob-code :target-id "ref-wire-sx-post"
|
||||
:text (str "(span :class \"text-stone-800 text-sm\" \"Hello, \" (strong \"" name "\") \"!\")")))))
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
(&key)
|
||||
(let ((status (helper "request-form" "status" "unknown")))
|
||||
(<>
|
||||
(span :class "text-stone-700 text-sm" "Status: " (strong status) " — updated via PUT")
|
||||
(span (~tw :tokens "text-stone-700 text-sm") "Status: " (strong status) " — updated via PUT")
|
||||
(~docs/oob-code :target-id "ref-wire-sx-put"
|
||||
:text (str "(span :class \"text-stone-700 text-sm\" \"Status: \" (strong \"" status "\") \" — updated via PUT\")")))))
|
||||
|
||||
@@ -82,8 +82,8 @@
|
||||
(str "(span :class \"text-stone-800 text-sm\" \"Results for: \" (strong \"" q "\"))"))))
|
||||
(<>
|
||||
(if (= q "")
|
||||
(span :class "text-stone-400 text-sm" "Start typing to trigger a search.")
|
||||
(span :class "text-stone-800 text-sm" "Results for: " (strong q)))
|
||||
(span (~tw :tokens "text-stone-400 text-sm") "Start typing to trigger a search.")
|
||||
(span (~tw :tokens "text-stone-800 text-sm") "Results for: " (strong q)))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-trigger" :text sx-text)))))
|
||||
|
||||
;; --- sx-swap demo ---
|
||||
@@ -95,7 +95,7 @@
|
||||
(&key)
|
||||
(let ((now (helper "now" "%H:%M:%S")))
|
||||
(<>
|
||||
(div :class "text-sm text-violet-700" (str "New item (" now ")"))
|
||||
(div (~tw :tokens "text-sm text-violet-700") (str "New item (" now ")"))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-swap"
|
||||
:text (str "(div :class \"text-sm text-violet-700\" \"New item (" now ")\")")))))
|
||||
|
||||
@@ -108,9 +108,9 @@
|
||||
(&key)
|
||||
(let ((now (helper "now" "%H:%M:%S")))
|
||||
(<>
|
||||
(span :class "text-emerald-700 text-sm" "Main updated at " now)
|
||||
(span (~tw :tokens "text-emerald-700 text-sm") "Main updated at " now)
|
||||
(div :id "ref-oob-side" :sx-swap-oob "innerHTML"
|
||||
(span :class "text-violet-700 text-sm" "OOB updated at " now))
|
||||
(span (~tw :tokens "text-violet-700 text-sm") "OOB updated at " now))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-swap-oob"
|
||||
:text (str "(<> (span ... \"" now "\") (div :id \"ref-oob-side\" :sx-swap-oob \"innerHTML\" ...))")))))
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
(<>
|
||||
(div :id "the-header" (h3 "Page header — not selected"))
|
||||
(div :id "the-content"
|
||||
(span :class "text-emerald-700 text-sm"
|
||||
(span (~tw :tokens "text-emerald-700 text-sm")
|
||||
"This fragment was selected from a larger response. Time: " now))
|
||||
(div :id "the-footer" (p "Page footer — not selected"))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-select"
|
||||
@@ -141,7 +141,7 @@
|
||||
(let ((q (helper "request-arg" "q" "")))
|
||||
(sleep 800)
|
||||
(<>
|
||||
(span :class "text-stone-800 text-sm" "Echo: " (strong q))
|
||||
(span (~tw :tokens "text-stone-800 text-sm") "Echo: " (strong q))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-sync"
|
||||
:text (str "(span :class \"text-stone-800 text-sm\" \"Echo: \" (strong \"" q "\"))")))))
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
(&key)
|
||||
(let ((name (helper "request-header" "SX-Prompt" "anonymous")))
|
||||
(<>
|
||||
(span :class "text-stone-800 text-sm" "Hello, " (strong name) "!")
|
||||
(span (~tw :tokens "text-stone-800 text-sm") "Hello, " (strong name) "!")
|
||||
(~docs/oob-code :target-id "ref-wire-sx-prompt"
|
||||
:text (str "(span :class \"text-stone-800 text-sm\" \"Hello, \" (strong \"" name "\") \"!\")")))))
|
||||
|
||||
@@ -184,7 +184,7 @@
|
||||
(let ((display (if (nil? name) "(no file)" name)))
|
||||
(let ((sx-text (str "(span :class \"text-stone-800 text-sm\" \"Received: \" (strong \"" display "\"))")))
|
||||
(<>
|
||||
(span :class "text-stone-800 text-sm" "Received: " (strong display))
|
||||
(span (~tw :tokens "text-stone-800 text-sm") "Received: " (strong display))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-encoding" :text sx-text))))))
|
||||
|
||||
;; --- sx-headers demo: echo custom headers ---
|
||||
@@ -206,8 +206,8 @@
|
||||
")"))))
|
||||
(<>
|
||||
(if (empty? custom)
|
||||
(span :class "text-stone-400 text-sm" "No custom headers received.")
|
||||
(ul :class "text-sm text-stone-700 space-y-1"
|
||||
(span (~tw :tokens "text-stone-400 text-sm") "No custom headers received.")
|
||||
(ul (~tw :tokens "text-sm text-stone-700 space-y-1")
|
||||
(map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) custom)))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-headers" :text sx-text))))))
|
||||
|
||||
@@ -227,8 +227,8 @@
|
||||
")"))))
|
||||
(<>
|
||||
(if (empty? vals)
|
||||
(span :class "text-stone-400 text-sm" "No values received.")
|
||||
(ul :class "text-sm text-stone-700 space-y-1"
|
||||
(span (~tw :tokens "text-stone-400 text-sm") "No values received.")
|
||||
(ul (~tw :tokens "text-sm text-stone-700 space-y-1")
|
||||
(map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) vals)))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-include" :text sx-text)))))
|
||||
|
||||
@@ -249,8 +249,8 @@
|
||||
")"))))
|
||||
(<>
|
||||
(if (empty? vals)
|
||||
(span :class "text-stone-400 text-sm" "No values received.")
|
||||
(ul :class "text-sm text-stone-700 space-y-1"
|
||||
(span (~tw :tokens "text-stone-400 text-sm") "No values received.")
|
||||
(ul (~tw :tokens "text-sm text-stone-700 space-y-1")
|
||||
(map (fn (pair) (li (strong (first pair)) ": " (nth pair 1))) vals)))
|
||||
(~docs/oob-code :target-id "ref-wire-sx-vals" :text sx-text)))))
|
||||
|
||||
@@ -270,7 +270,7 @@
|
||||
"")
|
||||
(let ((sx-text (str "(span :class \"text-emerald-700 text-sm\" \"Success on attempt \" \"" n "\" \"!\")")))
|
||||
(<>
|
||||
(span :class "text-emerald-700 text-sm" "Success on attempt " (str n) "!")
|
||||
(span (~tw :tokens "text-emerald-700 text-sm") "Success on attempt " (str n) "!")
|
||||
(~docs/oob-code :target-id "ref-wire-sx-retry" :text sx-text)))))))
|
||||
|
||||
;; --- sx-trigger-event demo: response header triggers ---
|
||||
@@ -283,7 +283,7 @@
|
||||
(let ((now (helper "now" "%H:%M:%S")))
|
||||
(set-response-header "SX-Trigger" "showNotice")
|
||||
(<>
|
||||
(span :class "text-stone-800 text-sm" "Loaded at " (strong now) " — check the border!"))))
|
||||
(span (~tw :tokens "text-stone-800 text-sm") "Loaded at " (strong now) " — check the border!"))))
|
||||
|
||||
;; --- sx-retarget demo: response header retargets ---
|
||||
|
||||
@@ -295,4 +295,4 @@
|
||||
(let ((now (helper "now" "%H:%M:%S")))
|
||||
(set-response-header "SX-Retarget" "#ref-hdr-retarget-alt")
|
||||
(<>
|
||||
(span :class "text-violet-700 text-sm" "Retargeted at " (strong now)))))
|
||||
(span (~tw :tokens "text-violet-700 text-sm") "Retargeted at " (strong now)))))
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
(if
|
||||
(or (= filename "") (= def-name ""))
|
||||
(div
|
||||
:class "text-sm text-stone-400 p-2"
|
||||
(~tw :tokens "text-sm text-stone-400 p-2")
|
||||
"Missing file or name parameter")
|
||||
(let
|
||||
((d (spec-explore-define filename def-name)))
|
||||
@@ -18,5 +18,5 @@
|
||||
d
|
||||
(~specs-explorer/spec-explorer-define-detail :d d :filename filename)
|
||||
(div
|
||||
:class "text-sm text-stone-400 p-2"
|
||||
(~tw :tokens "text-sm text-stone-400 p-2")
|
||||
(str "Definition '" def-name "' not found in " filename)))))))
|
||||
|
||||
Reference in New Issue
Block a user