Files
rose-ash/sx/sx/page-functions.sx
giles de80d921e9 Prefix all SX URLs with /sx/ for WhatsApp-safe sharing
All routes moved under /sx/ prefix:
- / redirects to /sx/
- /sx/ serves home page
- /sx/<path:expr> is the catch-all for SX expression URLs
- Bare /(...) and /~... redirect to /sx/(...) and /sx/~...
- All ~600 hrefs, sx-get attrs, defhandler paths, redirect
  targets, and blueprint routes updated across 44 files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 19:07:09 +00:00

528 lines
22 KiB
Plaintext

;; SX docs page functions — section + page dispatch for GraphSX URL routing.
;;
;; IMPORTANT: Page functions return QUOTED expressions (unevaluated ASTs).
;; The Python router evaluates these functions with async_eval to get the AST,
;; then passes it through _eval_slot (aser) for component expansion and HTML
;; tag handling. This two-phase approach is necessary because eval_expr doesn't
;; handle HTML tags — only the aser/render paths do.
;;
;; Pattern:
;; Simple: '(~component-name)
;; Data: (let ((data (helper))) `(~component :key ,val))
;;
;; URL eval: /(language.(doc.introduction))
;; → (language (doc "introduction"))
;; → async_eval returns [Symbol("~docs-introduction-content")]
;; → _eval_slot wraps in (~sx-doc :path "..." <ast>) and renders via aser
;;
;; NOTE: Lambda &rest is not supported by call-lambda in the current spec.
;; All functions take explicit positional params; missing args default to nil.
;; ---------------------------------------------------------------------------
;; Section functions — structural, pass through content or return index
;; ---------------------------------------------------------------------------
(define home
(fn (content)
(if (nil? content) '(~sx-home-content) content)))
(define language
(fn (content)
(if (nil? content) nil content)))
(define geography
(fn (content)
(if (nil? content) nil content)))
(define applications
(fn (content)
(if (nil? content) nil content)))
(define etc
(fn (content)
(if (nil? content) nil content)))
;; Sub-section functions
(define hypermedia
(fn (content)
(if (nil? content) nil content)))
(define reactive
(fn (slug)
(if (nil? slug)
'(~reactive-islands-index-content)
(case slug
"demo" '(~reactive-islands-demo-content)
"event-bridge" '(~reactive-islands-event-bridge-content)
"named-stores" '(~reactive-islands-named-stores-content)
"plan" '(~reactive-islands-plan-content)
"phase2" '(~reactive-islands-phase2-content)
:else '(~reactive-islands-index-content)))))
(define marshes
(fn (content)
(if (nil? content) '(~reactive-islands-marshes-content) content)))
(define isomorphism
(fn (slug)
(if (nil? slug)
'(~plan-isomorphic-content)
(case slug
"bundle-analyzer"
(let ((data (bundle-analyzer-data)))
`(~bundle-analyzer-content
:pages ,(get data "pages")
:total-components ,(get data "total-components")
:total-macros ,(get data "total-macros")
:pure-count ,(get data "pure-count")
:io-count ,(get data "io-count")))
"routing-analyzer"
(let ((data (routing-analyzer-data)))
`(~routing-analyzer-content
:pages ,(get data "pages")
:total-pages ,(get data "total-pages")
:client-count ,(get data "client-count")
:server-count ,(get data "server-count")
:registry-sample ,(get data "registry-sample")))
"data-test"
(let ((data (data-test-data)))
`(~data-test-content
:server-time ,(get data "server-time")
:items ,(get data "items")
:phase ,(get data "phase")
:transport ,(get data "transport")))
"async-io" '(~async-io-demo-content)
"affinity"
(let ((data (affinity-demo-data)))
`(~affinity-demo-content
:components ,(get data "components")
:page-plans ,(get data "page-plans")))
"optimistic"
(let ((data (optimistic-demo-data)))
`(~optimistic-demo-content
:items ,(get data "items")
:server-time ,(get data "server-time")))
"offline"
(let ((data (offline-demo-data)))
`(~offline-demo-content
:notes ,(get data "notes")
:server-time ,(get data "server-time")))
;; "streaming" → handled as special case by Python router
:else '(~plan-isomorphic-content)))))
;; ---------------------------------------------------------------------------
;; Page functions — leaf dispatch to content components
;; ---------------------------------------------------------------------------
;; Docs (under language)
(define doc
(fn (slug)
(if (nil? slug)
'(~docs-introduction-content)
(case slug
"introduction" '(~docs-introduction-content)
"getting-started" '(~docs-getting-started-content)
"components" '(~docs-components-content)
"evaluator" '(~docs-evaluator-content)
"primitives"
(let ((data (primitives-data)))
`(~docs-primitives-content
:prims (~doc-primitives-tables :primitives ,data)))
"special-forms"
(let ((data (special-forms-data)))
`(~docs-special-forms-content
:forms (~doc-special-forms-tables :forms ,data)))
"server-rendering" '(~docs-server-rendering-content)
:else '(~docs-introduction-content)))))
;; Specs (under language)
(define spec
(fn (slug)
(if (nil? slug)
'(~spec-architecture-content)
(case slug
"core"
(let ((files (make-spec-files core-spec-items)))
`(~spec-overview-content :spec-title "Core Language" :spec-files ,files))
"adapters"
(let ((files (make-spec-files adapter-spec-items)))
`(~spec-overview-content :spec-title "Adapters" :spec-files ,files))
"browser"
(let ((files (make-spec-files browser-spec-items)))
`(~spec-overview-content :spec-title "Browser Runtime" :spec-files ,files))
"reactive"
(let ((files (make-spec-files reactive-spec-items)))
`(~spec-overview-content :spec-title "Reactive System" :spec-files ,files))
"host"
(let ((files (make-spec-files host-spec-items)))
`(~spec-overview-content :spec-title "Host Interface" :spec-files ,files))
"extensions"
(let ((files (make-spec-files extension-spec-items)))
`(~spec-overview-content :spec-title "Extensions" :spec-files ,files))
:else (let ((found-spec (find-spec slug)))
(if found-spec
(let ((src (read-spec-file (get found-spec "filename"))))
`(~spec-detail-content
:spec-title ,(get found-spec "title")
:spec-desc ,(get found-spec "desc")
:spec-filename ,(get found-spec "filename")
:spec-source ,src
:spec-prose ,(get found-spec "prose")))
`(~spec-not-found :slug ,slug)))))))
;; Spec explorer (under language → spec)
(define explore
(fn (slug)
(if (nil? slug)
'(~spec-architecture-content)
(let ((found-spec (find-spec slug)))
(if found-spec
(let ((data (spec-explorer-data
(get found-spec "filename")
(get found-spec "title")
(get found-spec "desc"))))
(if data
`(~spec-explorer-content :data ,data)
`(~spec-not-found :slug ,slug)))
`(~spec-not-found :slug ,slug))))))
;; Helper used by spec — make-spec-files
(define make-spec-files
(fn (items)
(map (fn (item)
(dict :title (get item "title") :desc (get item "desc")
:prose (get item "prose")
:filename (get item "filename") :href (str "/sx/(language.(spec." (get item "slug") "))")
:source (read-spec-file (get item "filename"))))
items)))
;; Bootstrappers (under language)
(define bootstrapper
(fn (slug)
(if (nil? slug)
'(~bootstrappers-index-content)
(let ((data (bootstrapper-data slug)))
(if (get data "bootstrapper-not-found")
`(~spec-not-found :slug ,slug)
(case slug
"self-hosting"
`(~bootstrapper-self-hosting-content
:py-sx-source ,(get data "py-sx-source")
:g0-output ,(get data "g0-output")
:g1-output ,(get data "g1-output")
:defines-matched ,(get data "defines-matched")
:defines-total ,(get data "defines-total")
:g0-lines ,(get data "g0-lines")
:g0-bytes ,(get data "g0-bytes")
:verification-status ,(get data "verification-status"))
"self-hosting-js"
`(~bootstrapper-self-hosting-js-content
:js-sx-source ,(get data "js-sx-source")
:defines-matched ,(get data "defines-matched")
:defines-total ,(get data "defines-total")
:js-sx-lines ,(get data "js-sx-lines")
:verification-status ,(get data "verification-status"))
"python"
`(~bootstrapper-py-content
:bootstrapper-source ,(get data "bootstrapper-source")
:bootstrapped-output ,(get data "bootstrapped-output"))
"page-helpers"
(let ((ph-data (page-helpers-demo-data)))
`(~page-helpers-demo-content
:sf-categories ,(get ph-data "sf-categories")
:sf-total ,(get ph-data "sf-total")
:sf-ms ,(get ph-data "sf-ms")
:ref-sample ,(get ph-data "ref-sample")
:ref-ms ,(get ph-data "ref-ms")
:attr-result ,(get ph-data "attr-result")
:attr-ms ,(get ph-data "attr-ms")
:comp-source ,(get ph-data "comp-source")
:comp-ms ,(get ph-data "comp-ms")
:routing-result ,(get ph-data "routing-result")
:routing-ms ,(get ph-data "routing-ms")
:server-total-ms ,(get ph-data "server-total-ms")
:sf-source ,(get ph-data "sf-source")
:attr-detail ,(get ph-data "attr-detail")
:req-attrs ,(get ph-data "req-attrs")
:attr-keys ,(get ph-data "attr-keys")))
:else
`(~bootstrapper-js-content
:bootstrapper-source ,(get data "bootstrapper-source")
:bootstrapped-output ,(get data "bootstrapped-output"))))))))
;; Testing (under language)
(define test
(fn (slug)
(if (nil? slug)
(let ((data (run-modular-tests "all")))
`(~testing-overview-content
:server-results ,(get data "server-results")
:framework-source ,(get data "framework-source")
:eval-source ,(get data "eval-source")
:parser-source ,(get data "parser-source")
:router-source ,(get data "router-source")
:render-source ,(get data "render-source")
:deps-source ,(get data "deps-source")
:engine-source ,(get data "engine-source")))
(case slug
"runners" '(~testing-runners-content)
:else
(let ((data (run-modular-tests slug)))
(case slug
"eval" `(~testing-spec-content
:spec-name "eval" :spec-title "Evaluator Tests"
:spec-desc "81 tests covering the core evaluator and all primitives."
:spec-source ,(get data "spec-source")
:framework-source ,(get data "framework-source")
:server-results ,(get data "server-results"))
"parser" `(~testing-spec-content
:spec-name "parser" :spec-title "Parser Tests"
:spec-desc "39 tests covering tokenization and parsing."
:spec-source ,(get data "spec-source")
:framework-source ,(get data "framework-source")
:server-results ,(get data "server-results"))
"router" `(~testing-spec-content
:spec-name "router" :spec-title "Router Tests"
:spec-desc "18 tests covering client-side route matching."
:spec-source ,(get data "spec-source")
:framework-source ,(get data "framework-source")
:server-results ,(get data "server-results"))
"render" `(~testing-spec-content
:spec-name "render" :spec-title "Renderer Tests"
:spec-desc "23 tests covering HTML rendering."
:spec-source ,(get data "spec-source")
:framework-source ,(get data "framework-source")
:server-results ,(get data "server-results"))
"deps" `(~testing-spec-content
:spec-name "deps" :spec-title "Dependency Analysis Tests"
:spec-desc "33 tests covering component dependency analysis."
:spec-source ,(get data "spec-source")
:framework-source ,(get data "framework-source")
:server-results ,(get data "server-results"))
"engine" `(~testing-spec-content
:spec-name "engine" :spec-title "Engine Tests"
:spec-desc "37 tests covering engine pure functions."
:spec-source ,(get data "spec-source")
:framework-source ,(get data "framework-source")
:server-results ,(get data "server-results"))
"orchestration" `(~testing-spec-content
:spec-name "orchestration" :spec-title "Orchestration Tests"
:spec-desc "17 tests covering orchestration."
:spec-source ,(get data "spec-source")
:framework-source ,(get data "framework-source")
:server-results ,(get data "server-results"))
:else `(~testing-overview-content
:server-results ,(get data "server-results"))))))))
;; Reference (under geography → hypermedia)
(define reference
(fn (slug)
(if (nil? slug)
'(~reference-index-content)
(let ((data (reference-data slug)))
(case slug
"attributes" `(~reference-attrs-content
:req-table (~doc-attr-table-from-data :title "Request Attributes" :attrs ,(get data "req-attrs"))
:beh-table (~doc-attr-table-from-data :title "Behavior Attributes" :attrs ,(get data "beh-attrs"))
:uniq-table (~doc-attr-table-from-data :title "Unique to sx" :attrs ,(get data "uniq-attrs")))
"headers" `(~reference-headers-content
:req-table (~doc-headers-table-from-data :title "Request Headers" :headers ,(get data "req-headers"))
:resp-table (~doc-headers-table-from-data :title "Response Headers" :headers ,(get data "resp-headers")))
"events" `(~reference-events-content
:table (~doc-two-col-table-from-data
:intro "sx fires custom DOM events at various points in the request lifecycle."
:col1 "Event" :col2 "Description" :items ,(get data "events-list")))
"js-api" `(~reference-js-api-content
:table (~doc-two-col-table-from-data
:intro "The client-side sx.js library exposes a public API for programmatic use."
:col1 "Method" :col2 "Description" :items ,(get data "js-api-list")))
:else `(~reference-attrs-content
:req-table (~doc-attr-table-from-data :title "Request Attributes" :attrs ,(get data "req-attrs"))
:beh-table (~doc-attr-table-from-data :title "Behavior Attributes" :attrs ,(get data "beh-attrs"))
:uniq-table (~doc-attr-table-from-data :title "Unique to sx" :attrs ,(get data "uniq-attrs"))))))))
;; Reference detail pages (under geography → hypermedia → reference)
;; Takes two positional args: kind and slug
(define reference-detail
(fn (kind slug)
(if (nil? slug) nil
(case kind
"attributes"
(let ((data (attr-detail-data slug)))
(if (get data "attr-not-found")
`(~reference-attr-not-found :slug ,slug)
`(~reference-attr-detail-content
:title ,(get data "attr-title")
:description ,(get data "attr-description")
:demo ,(get data "attr-demo")
:example-code ,(get data "attr-example")
:handler-code ,(get data "attr-handler")
:wire-placeholder-id ,(get data "attr-wire-id"))))
"headers"
(let ((data (header-detail-data slug)))
(if (get data "header-not-found")
`(~reference-attr-not-found :slug ,slug)
`(~reference-header-detail-content
:title ,(get data "header-title")
:direction ,(get data "header-direction")
:description ,(get data "header-description")
:example-code ,(get data "header-example")
:demo ,(get data "header-demo"))))
"events"
(let ((data (event-detail-data slug)))
(if (get data "event-not-found")
`(~reference-attr-not-found :slug ,slug)
`(~reference-event-detail-content
:title ,(get data "event-title")
:description ,(get data "event-description")
:example-code ,(get data "event-example")
:demo ,(get data "event-demo"))))
:else nil))))
;; Examples (under geography → hypermedia)
(define example
(fn (slug)
(if (nil? slug)
nil
(case slug
"click-to-load" '(~example-click-to-load)
"form-submission" '(~example-form-submission)
"polling" '(~example-polling)
"delete-row" '(~example-delete-row)
"inline-edit" '(~example-inline-edit)
"oob-swaps" '(~example-oob-swaps)
"lazy-loading" '(~example-lazy-loading)
"infinite-scroll" '(~example-infinite-scroll)
"progress-bar" '(~example-progress-bar)
"active-search" '(~example-active-search)
"inline-validation" '(~example-inline-validation)
"value-select" '(~example-value-select)
"reset-on-submit" '(~example-reset-on-submit)
"edit-row" '(~example-edit-row)
"bulk-update" '(~example-bulk-update)
"swap-positions" '(~example-swap-positions)
"select-filter" '(~example-select-filter)
"tabs" '(~example-tabs)
"animations" '(~example-animations)
"dialogs" '(~example-dialogs)
"keyboard-shortcuts" '(~example-keyboard-shortcuts)
"put-patch" '(~example-put-patch)
"json-encoding" '(~example-json-encoding)
"vals-and-headers" '(~example-vals-and-headers)
"loading-states" '(~example-loading-states)
"sync-replace" '(~example-sync-replace)
"retry" '(~example-retry)
:else '(~example-click-to-load)))))
;; SX URLs (under applications)
(define sx-urls
(fn (slug)
'(~sx-urls-content)))
;; CSSX (under applications)
(define cssx
(fn (slug)
(if (nil? slug)
'(~cssx-overview-content)
(case slug
"patterns" '(~cssx-patterns-content)
"delivery" '(~cssx-delivery-content)
"async" '(~cssx-async-content)
"live" '(~cssx-live-content)
"comparisons" '(~cssx-comparison-content)
"philosophy" '(~cssx-philosophy-content)
:else '(~cssx-overview-content)))))
;; Protocols (under applications)
(define protocol
(fn (slug)
(if (nil? slug)
'(~protocol-wire-format-content)
(case slug
"wire-format" '(~protocol-wire-format-content)
"fragments" '(~protocol-fragments-content)
"resolver-io" '(~protocol-resolver-io-content)
"internal-services" '(~protocol-internal-services-content)
"activitypub" '(~protocol-activitypub-content)
"future" '(~protocol-future-content)
:else '(~protocol-wire-format-content)))))
;; Essays (under etc)
(define essay
(fn (slug)
(if (nil? slug)
'(~essays-index-content)
(case slug
"sx-sucks" '(~essay-sx-sucks)
"why-sexps" '(~essay-why-sexps)
"htmx-react-hybrid" '(~essay-htmx-react-hybrid)
"on-demand-css" '(~essay-on-demand-css)
"client-reactivity" '(~essay-client-reactivity)
"sx-native" '(~essay-sx-native)
"tail-call-optimization" '(~essay-tail-call-optimization)
"continuations" '(~essay-continuations)
"reflexive-web" '(~essay-reflexive-web)
"server-architecture" '(~essay-server-architecture)
"separation-of-concerns" '(~essay-separation-of-concerns)
"sx-and-ai" '(~essay-sx-and-ai)
"no-alternative" '(~essay-no-alternative)
"zero-tooling" '(~essay-zero-tooling)
"react-is-hypermedia" '(~essay-react-is-hypermedia)
"hegelian-synthesis" '(~essay-hegelian-synthesis)
"the-art-chain" '(~essay-the-art-chain)
"self-defining-medium" '(~essay-self-defining-medium)
:else '(~essays-index-content)))))
;; Philosophy (under etc)
(define philosophy
(fn (slug)
(if (nil? slug)
'(~philosophy-index-content)
(case slug
"sx-manifesto" '(~essay-sx-manifesto)
"godel-escher-bach" '(~essay-godel-escher-bach)
"wittgenstein" '(~essay-sx-and-wittgenstein)
"dennett" '(~essay-sx-and-dennett)
"existentialism" '(~essay-s-existentialism)
:else '(~philosophy-index-content)))))
;; Plans (under etc)
(define plan
(fn (slug)
(if (nil? slug)
'(~plans-index-content)
(case slug
"status" '(~plan-status-content)
"reader-macros" '(~plan-reader-macros-content)
"reader-macro-demo" '(~plan-reader-macro-demo-content)
"theorem-prover"
(let ((data (prove-data)))
'(~plan-theorem-prover-content))
"self-hosting-bootstrapper" '(~plan-self-hosting-bootstrapper-content)
"js-bootstrapper" '(~plan-js-bootstrapper-content)
"sx-activity" '(~plan-sx-activity-content)
"predictive-prefetch" '(~plan-predictive-prefetch-content)
"content-addressed-components" '(~plan-content-addressed-components-content)
"environment-images" '(~plan-environment-images-content)
"runtime-slicing" '(~plan-runtime-slicing-content)
"typed-sx" '(~plan-typed-sx-content)
"nav-redesign" '(~plan-nav-redesign-content)
"fragment-protocol" '(~plan-fragment-protocol-content)
"glue-decoupling" '(~plan-glue-decoupling-content)
"social-sharing" '(~plan-social-sharing-content)
"sx-ci" '(~plan-sx-ci-content)
"live-streaming" '(~plan-live-streaming-content)
"sx-web-platform" '(~plan-sx-web-platform-content)
"sx-forge" '(~plan-sx-forge-content)
"sx-swarm" '(~plan-sx-swarm-content)
"sx-proxy" '(~plan-sx-proxy-content)
"async-eval-convergence" '(~plan-async-eval-convergence-content)
"wasm-bytecode-vm" '(~plan-wasm-bytecode-vm-content)
"generative-sx" '(~plan-generative-sx-content)
"art-dag-sx" '(~plan-art-dag-sx-content)
"spec-explorer" '(~plan-spec-explorer-content)
"sx-urls" '(~plan-sx-urls-content)
"sx-protocol" '(~plan-sx-protocol-content)
:else '(~plans-index-content)))))