From 17b2df108edbcbc5a223b9d5c2b075dab22416e6 Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 27 Mar 2026 16:07:49 +0000 Subject: [PATCH] =?UTF-8?q?Refactor=20nav-tree.sx:=20one-liner=20dict=20?= =?UTF-8?q?=E2=86=92=20structured=20(dict=20...)=20forms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The nav tree was a 4KB single-line dict literal that was impossible to read, edit, or diff. Converted to explicit (dict :key val ...) calls with proper indentation. Now 100+ lines, each nav entry on its own line. Also added Native Browser to the applications section of the nav tree (was missing — the entry existed in nav-data.sx but not in the tree that the sidebar actually renders from). Co-Authored-By: Claude Opus 4.6 (1M context) --- sx/sx/nav-tree.sx | 215 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 205 insertions(+), 10 deletions(-) diff --git a/sx/sx/nav-tree.sx b/sx/sx/nav-tree.sx index e8eb56cc..6b0c905c 100644 --- a/sx/sx/nav-tree.sx +++ b/sx/sx/nav-tree.sx @@ -1,16 +1,211 @@ -;; Navigation tree structure and utility functions +(define + find-current + (fn + (items slug) + (when + slug + (some + (fn + (item) + (when + (ends-with? (get item "href") (str "." slug "))")) + (get item "label"))) + items)))) -(define find-current (fn (items slug) (when slug (some (fn (item) (when (ends-with? (get item "href") (str "." slug "))")) (get item "label"))) items)))) +(defcomp + ~nav-data/section-nav + (&key items current) + (<> + (map + (fn + (item) + (~shared:layout/nav-link + :href (get item "href") + :label (get item "label") + :is-selected (when (= (get item "label") current) "true") + :select-colours "aria-selected:bg-violet-200 aria-selected:text-violet-900")) + items))) -(defcomp ~nav-data/section-nav (&key items current) (<> (map (fn (item) (~shared:layout/nav-link :href (get item "href") :label (get item "label") :is-selected (when (= (get item "label") current) "true") :select-colours "aria-selected:bg-violet-200 aria-selected:text-violet-900")) items))) +(define + sx-nav-tree + (dict + :href "/sx/" + :label "sx" + :children (list + (dict + :href "/sx/(geography)" + :label "Geography" + :children (list + (dict + :href "/sx/(geography.(reactive))" + :label "Reactive Islands" + :children reactive-islands-nav-items) + (dict + :href "/sx/(geography.(hypermedia))" + :label "Hypermedia Lakes" + :children (list + (dict + :href "/sx/(geography.(hypermedia.(reference)))" + :label "Reference" + :children reference-nav-items) + (dict + :href "/sx/(geography.(hypermedia.(example)))" + :label "Examples" + :children examples-nav-items))) + (dict + :href "/sx/(geography.(scopes))" + :label "Scopes" + :summary "The unified primitive beneath provide, collect!, spreads, and islands. Named scope with downward value, upward accumulation, and a dedup flag.") + (dict + :href "/sx/(geography.(provide))" + :label "Provide / Emit!" + :summary "Sugar for scope-with-value. Render-time dynamic scope — the substrate beneath spreads, CSSX, and script collection.") + (dict + :href "/sx/(geography.(spreads))" + :label "Spreads" + :summary "Child-to-parent communication across render boundaries — spread, collect!, reactive-spread, built on scopes.") + (dict + :href "/sx/(geography.(marshes))" + :label "Marshes" + :children marshes-examples-nav-items + :summary "Where reactivity and hypermedia interpenetrate — server writes to signals, reactive transforms reshape server content, client state modifies how hypermedia is interpreted.") + (dict + :href "/sx/(geography.(isomorphism))" + :label "Isomorphism" + :children isomorphism-nav-items) + (dict + :href "/sx/(geography.(cek))" + :label "CEK Machine" + :children cek-nav-items))) + (dict + :href "/sx/(language)" + :label "Language" + :children (list + (dict + :href "/sx/(language.(doc))" + :label "Docs" + :children docs-nav-items) + (dict + :href "/sx/(language.(spec))" + :label "Specs" + :children specs-nav-items) + (dict + :href "/sx/(language.(spec.(explore.evaluator)))" + :label "Spec Explorer") + (dict + :href "/sx/(language.(bootstrapper))" + :label "Bootstrappers" + :children bootstrappers-nav-items) + (dict + :href "/sx/(language.(test))" + :label "Testing" + :children testing-nav-items))) + (dict + :href "/sx/(applications)" + :label "Applications" + :children (list + (dict :href "/sx/(applications.(sx-urls))" :label "SX URLs") + (dict + :href "/sx/(applications.(cssx))" + :label "CSSX" + :children cssx-nav-items) + (dict + :href "/sx/(applications.(protocol))" + :label "Protocols" + :children protocols-nav-items) + (dict :href "/sx/(applications.(sx-pub))" :label "sx-pub") + (dict + :href "/sx/(applications.(reactive-runtime))" + :label "Reactive Runtime" + :children reactive-runtime-nav-items) + (dict + :href "/sx/(applications.(native-browser))" + :label "Native Browser"))) + (dict :href "/sx/(tools)" :label "Tools" :children tools-nav-items) + (dict + :href "/sx/(etc)" + :label "Etc" + :children (list + (dict + :href "/sx/(etc.(essay))" + :label "Essays" + :children essays-nav-items) + (dict + :href "/sx/(etc.(philosophy))" + :label "Philosophy" + :children philosophy-nav-items) + (dict + :href "/sx/(etc.(plan))" + :label "Plans" + :children plans-nav-items)))))) -(define sx-nav-tree {:href "/sx/" :children (list {:href "/sx/(geography)" :children (list {:href "/sx/(geography.(reactive))" :children reactive-islands-nav-items :label "Reactive Islands"} {:href "/sx/(geography.(hypermedia))" :children (list {:href "/sx/(geography.(hypermedia.(reference)))" :children reference-nav-items :label "Reference"} {:href "/sx/(geography.(hypermedia.(example)))" :children examples-nav-items :label "Examples"}) :label "Hypermedia Lakes"} {:href "/sx/(geography.(scopes))" :summary "The unified primitive beneath provide, collect!, spreads, and islands. Named scope with downward value, upward accumulation, and a dedup flag." :label "Scopes"} {:href "/sx/(geography.(provide))" :summary "Sugar for scope-with-value. Render-time dynamic scope — the substrate beneath spreads, CSSX, and script collection." :label "Provide / Emit!"} {:href "/sx/(geography.(spreads))" :summary "Child-to-parent communication across render boundaries — spread, collect!, reactive-spread, built on scopes." :label "Spreads"} {:href "/sx/(geography.(marshes))" :children marshes-examples-nav-items :summary "Where reactivity and hypermedia interpenetrate — server writes to signals, reactive transforms reshape server content, client state modifies how hypermedia is interpreted." :label "Marshes"} {:href "/sx/(geography.(isomorphism))" :children isomorphism-nav-items :label "Isomorphism"} {:href "/sx/(geography.(cek))" :children cek-nav-items :label "CEK Machine"}) :label "Geography"} {:href "/sx/(language)" :children (list {:href "/sx/(language.(doc))" :children docs-nav-items :label "Docs"} {:href "/sx/(language.(spec))" :children specs-nav-items :label "Specs"} {:href "/sx/(language.(spec.(explore.evaluator)))" :label "Spec Explorer"} {:href "/sx/(language.(bootstrapper))" :children bootstrappers-nav-items :label "Bootstrappers"} {:href "/sx/(language.(test))" :children testing-nav-items :label "Testing"}) :label "Language"} {:href "/sx/(applications)" :children (list {:href "/sx/(applications.(sx-urls))" :label "SX URLs"} {:href "/sx/(applications.(cssx))" :children cssx-nav-items :label "CSSX"} {:href "/sx/(applications.(protocol))" :children protocols-nav-items :label "Protocols"} {:href "/sx/(applications.(sx-pub))" :label "sx-pub"} {:href "/sx/(applications.(reactive-runtime))" :children reactive-runtime-nav-items :label "Reactive Runtime"}) :label "Applications"} {:href "/sx/(tools)" :children tools-nav-items :label "Tools"} {:href "/sx/(etc)" :children (list {:href "/sx/(etc.(essay))" :children essays-nav-items :label "Essays"} {:href "/sx/(etc.(philosophy))" :children philosophy-nav-items :label "Philosophy"} {:href "/sx/(etc.(plan))" :children plans-nav-items :label "Plans"}) :label "Etc"}) :label "sx"}) +(define + has-descendant-href? + (fn + (node path) + (let + ((children (get node "children"))) + (when + children + (some + (fn + (child) + (or + (= (get child "href") path) + (has-descendant-href? child path))) + children))))) -(define has-descendant-href? (fn (node path) (let ((children (get node "children"))) (when children (some (fn (child) (or (= (get child "href") path) (has-descendant-href? child path))) children))))) +(define + find-nav-match + (fn + (items path) + (or + (some (fn (item) (when (= (get item "href") path) item)) items) + (some (fn (item) (when (has-descendant-href? item path) item)) items)))) -(define find-nav-match (fn (items path) (or (some (fn (item) (when (= (get item "href") path) item)) items) (some (fn (item) (when (has-descendant-href? item path) item)) items)))) - -(define resolve-nav-path (fn (tree path) (let ((trail (list))) (define walk (fn (node) (let ((children (get node "children"))) (when children (let ((match (find-nav-match children path))) (when match (append! trail {:siblings children :node match}) (when (not (= (get match "href") path)) (walk match)))))))) (walk tree) (let ((depth (len trail))) (if (= depth 0) {:children (get tree "children") :depth 0 :trail trail} (let ((deepest (nth trail (- depth 1)))) {:children (get (get deepest "node") "children") :depth depth :trail trail})))))) - -(define find-nav-index (fn (items node) (let ((target-href (get node "href")) (count (len items))) (define find-loop (fn (i) (if (>= i count) 0 (if (= (get (nth items i) "href") target-href) i (find-loop (+ i 1)))))) (find-loop 0)))) +(define + resolve-nav-path + (fn + (tree path) + (let + ((trail (list))) + (define + walk + (fn + (node) + (let + ((children (get node "children"))) + (when + children + (let + ((match (find-nav-match children path))) + (when + match + (append! trail {:siblings children :node match}) + (when (not (= (get match "href") path)) (walk match)))))))) + (walk tree) + (let + ((depth (len trail))) + (if + (= depth 0) + {:children (get tree "children") :depth 0 :trail trail} + (let ((deepest (nth trail (- depth 1)))) {:children (get (get deepest "node") "children") :depth depth :trail trail})))))) +(define + find-nav-index + (fn + (items node) + (let + ((target-href (get node "href")) (count (len items))) + (define + find-loop + (fn + (i) + (if + (>= i count) + 0 + (if + (= (get (nth items i) "href") target-href) + i + (find-loop (+ i 1)))))) + (find-loop 0))))