Add cond-scheme? primitive and parameter binding to tree editor render tab

Register cond-scheme? as OCaml primitive — was defined in spec/evaluator.sx
but never exposed to the browser runtime, causing render.sx to crash with
"Undefined symbol: cond-scheme?" on every SX response. This broke URL
updates on navigation (handle-history never ran after the rendering error).

Tree editor render tab now extracts &key params from defcomp/defisland
definitions and shows input fields. Values substitute into the rendered
preview live as you type. Inputs live outside the reactive cond branch
so signal updates don't steal focus.

sx-tools page function accepts &key params (title, etc.) forwarded to
the overview component.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 22:16:08 +00:00
parent 8c99ec4fac
commit 85702e92c9
4 changed files with 44 additions and 681 deletions

View File

@@ -785,6 +785,14 @@ let () =
| [Keyword "else"] -> Bool true
| [Bool true] -> Bool true
| _ -> Bool false);
register "cond-scheme?" (fun args ->
match args with
| [List clauses] ->
Bool (List.for_all (fun c ->
match c with
| List l -> List.length l = 2
| _ -> false) clauses)
| _ -> Bool false);
register "component?" (fun args ->
match args with [Component _] -> Bool true | [Island _] -> Bool true | _ -> Bool false);
register "lambda-closure" (fun args ->

View File

@@ -1,503 +1,67 @@
;; SX docs page functions — section + page dispatch for GraphSX URL routing.
;;
;; Page functions return QUOTED expressions (unevaluated ASTs).
;; The router evaluates these via the OCaml kernel (or Python fallback).
;;
;; Pattern:
;; Simple: '(~component-name)
;; Data: (let ((data (helper "name" arg))) `(~component :key ,val))
;;
;; IO: Application data is fetched via the (helper name ...) IO primitive,
;; which dispatches to Python page helpers through the coroutine bridge.
;; This keeps the spec clean — no application functions leak into the kernel.
(define slug->component (fn (slug prefix infix suffix) (if infix (make-symbol (str prefix slug infix slug suffix)) (make-symbol (str prefix slug suffix)))))
;; ---------------------------------------------------------------------------
;; Convention-based page dispatch
;; ---------------------------------------------------------------------------
;;
;; Most page functions are boilerplate: slug → component name via a naming
;; convention. Instead of hand-writing case statements, derive the component
;; symbol from the slug at runtime.
;;
;; Naming conventions:
;; essay: "sx-sucks" → ~essays/sx-sucks/essay-sx-sucks
;; plan: "status" → ~plans/status/plan-status-content
;; example: "tabs" → ~examples-content/example-tabs
;; protocol: "fragments" → ~protocols/fragments-content
;; cssx: "patterns" → ~cssx/patterns-content
;; ri-example: "counter" → ~reactive-islands/demo/example-counter
(define make-page-fn (fn (default-name prefix infix suffix) (fn (slug) (if (nil? slug) (list (make-symbol default-name)) (list (slug->component slug prefix infix suffix))))))
;; Build a component symbol from a slug and a naming pattern.
;; Pattern: prefix + slug + infix + slug + suffix
;; When infix is nil, slug appears once: prefix + slug + suffix
(define slug->component
(fn (slug prefix infix suffix)
(if infix
(make-symbol (str prefix slug infix slug suffix))
(make-symbol (str prefix slug suffix)))))
(define home (fn (content) (if (nil? content) (quote (~docs-content/home-content)) content)))
;; Make a simple slug-dispatcher: given a naming convention, returns a function
;; that maps (slug) → '(~derived-component-name).
;; default-name is a STRING of the component name for the nil-slug (index) case.
;; (We use a string + make-symbol because bare ~symbols get evaluated as lookups.)
(define make-page-fn
(fn (default-name prefix infix suffix)
(fn (slug)
(if (nil? slug)
(list (make-symbol default-name))
(list (slug->component slug prefix infix suffix))))))
(define language (fn (content) (if (nil? content) nil content)))
;; ---------------------------------------------------------------------------
;; Section functions — structural, pass through content or return index
;; ---------------------------------------------------------------------------
(define geography (fn (content) (if (nil? content) (quote (~geography/index-content)) content)))
(define home
(fn (content)
(if (nil? content) '(~docs-content/home-content) content)))
(define applications (fn (content) (if (nil? content) nil content)))
(define language
(fn (content)
(if (nil? content) nil content)))
(define etc (fn (content) (if (nil? content) nil content)))
(define geography
(fn (content)
(if (nil? content) '(~geography/index-content) content)))
(define hypermedia (fn (content) (if (nil? content) nil content)))
(define applications
(fn (content)
(if (nil? content) nil content)))
(define reactive (fn (content) (if (nil? content) (quote (~reactive-islands/index/reactive-islands-index-content)) content)))
(define etc
(fn (content)
(if (nil? content) nil content)))
(define examples (make-page-fn "~reactive-islands/demo/reactive-islands-demo-content" "~reactive-islands/demo/example-" nil ""))
;; Sub-section functions
(define cek (fn (slug) (if (nil? slug) (quote (~geography/cek/cek-content)) (case slug "demo" (quote (~geography/cek/cek-demo-content)) "freeze" (quote (~geography/cek/cek-freeze-content)) "content" (quote (~geography/cek/cek-content-address-content)) :else (quote (~geography/cek/cek-content))))))
(define hypermedia
(fn (content)
(if (nil? content) nil content)))
(define provide (fn (content) (if (nil? content) (quote (~geography/provide-content)) content)))
(define reactive
(fn (content)
(if (nil? content)
'(~reactive-islands/index/reactive-islands-index-content)
content)))
(define scopes (fn (content) (if (nil? content) (quote (~geography/scopes-content)) content)))
;; Convention: ~reactive-islands/demo/example-{slug}
(define examples
(make-page-fn "~reactive-islands/demo/reactive-islands-demo-content" "~reactive-islands/demo/example-" nil ""))
(define spreads (fn (content) (if (nil? content) (quote (~geography/spreads-content)) content)))
(define marshes (fn (slug) (if (nil? slug) (quote (~reactive-islands/marshes/reactive-islands-marshes-content)) (case slug "hypermedia-feeds" (quote (~reactive-islands/marshes/example-hypermedia-feeds)) "server-signals" (quote (~reactive-islands/marshes/example-server-signals)) "on-settle" (quote (~reactive-islands/marshes/example-on-settle)) "signal-triggers" (quote (~reactive-islands/marshes/example-signal-triggers)) "view-transform" (quote (~reactive-islands/marshes/example-view-transform)) :else (quote (~reactive-islands/marshes/reactive-islands-marshes-content))))))
(define cek
(fn (slug)
(if (nil? slug)
'(~geography/cek/cek-content)
(case slug
"demo" '(~geography/cek/cek-demo-content)
"freeze" '(~geography/cek/cek-freeze-content)
"content" '(~geography/cek/cek-content-address-content)
:else '(~geography/cek/cek-content)))))
(define isomorphism (fn (slug) (if (nil? slug) (quote (~plans/isomorphic/plan-isomorphic-content)) (case slug "bundle-analyzer" (let ((data (helper "bundle-analyzer-data"))) (quasiquote (~analyzer/bundle-analyzer-content :pages (unquote (get data "pages")) :total-components (unquote (get data "total-components")) :total-macros (unquote (get data "total-macros")) :pure-count (unquote (get data "pure-count")) :io-count (unquote (get data "io-count"))))) "routing-analyzer" (let ((data (helper "routing-analyzer-data"))) (quasiquote (~routing-analyzer/content :pages (unquote (get data "pages")) :total-pages (unquote (get data "total-pages")) :client-count (unquote (get data "client-count")) :server-count (unquote (get data "server-count")) :registry-sample (unquote (get data "registry-sample"))))) "data-test" (let ((data (helper "data-test-data"))) (quasiquote (~data-test/content :server-time (unquote (get data "server-time")) :items (unquote (get data "items")) :phase (unquote (get data "phase")) :transport (unquote (get data "transport"))))) "async-io" (quote (~async-io-demo/content)) "affinity" (let ((data (helper "affinity-demo-data"))) (quasiquote (~affinity-demo/content :components (unquote (get data "components")) :page-plans (unquote (get data "page-plans"))))) "optimistic" (let ((data (helper "optimistic-demo-data"))) (quasiquote (~optimistic-demo/content :items (unquote (get data "items")) :server-time (unquote (get data "server-time"))))) "offline" (let ((data (helper "offline-demo-data"))) (quasiquote (~offline-demo/content :notes (unquote (get data "notes")) :server-time (unquote (get data "server-time"))))) :else (quote (~plans/isomorphic/plan-isomorphic-content))))))
(define provide
(fn (content)
(if (nil? content) '(~geography/provide-content) content)))
(define doc (fn (slug) (if (nil? slug) (quote (~docs-content/docs-introduction-content)) (case slug "introduction" (quote (~docs-content/docs-introduction-content)) "getting-started" (quote (~docs-content/docs-getting-started-content)) "components" (quote (~docs-content/docs-components-content)) "evaluator" (quote (~docs-content/docs-evaluator-content)) "primitives" (let ((data (helper "primitives-data"))) (quasiquote (~docs-content/docs-primitives-content :prims (~docs/primitives-tables :primitives (unquote data))))) "special-forms" (let ((data (helper "special-forms-data"))) (quasiquote (~docs-content/docs-special-forms-content :forms (~docs/special-forms-tables :forms (unquote data))))) "server-rendering" (quote (~docs-content/docs-server-rendering-content)) :else (quote (~docs-content/docs-introduction-content))))))
(define scopes
(fn (content)
(if (nil? content) '(~geography/scopes-content) content)))
(define spec (fn (slug) (if (nil? slug) (quote (~specs/architecture-content)) (case slug "core" (let ((files (make-spec-files core-spec-items))) (quasiquote (~specs/overview-content :spec-title "Core Language" :spec-files (unquote files)))) "adapters" (let ((files (make-spec-files adapter-spec-items))) (quasiquote (~specs/overview-content :spec-title "Adapters" :spec-files (unquote files)))) "browser" (let ((files (make-spec-files browser-spec-items))) (quasiquote (~specs/overview-content :spec-title "Browser Runtime" :spec-files (unquote files)))) "reactive" (let ((files (make-spec-files reactive-spec-items))) (quasiquote (~specs/overview-content :spec-title "Reactive System" :spec-files (unquote files)))) "host" (let ((files (make-spec-files host-spec-items))) (quasiquote (~specs/overview-content :spec-title "Host Interface" :spec-files (unquote files)))) "extensions" (let ((files (make-spec-files extension-spec-items))) (quasiquote (~specs/overview-content :spec-title "Extensions" :spec-files (unquote files)))) :else (let ((found-spec (find-spec slug))) (if found-spec (let ((src (helper "read-spec-file" (get found-spec "filename")))) (quasiquote (~specs/detail-content :spec-title (unquote (get found-spec "title")) :spec-desc (unquote (get found-spec "desc")) :spec-filename (unquote (get found-spec "filename")) :spec-source (unquote src) :spec-prose (unquote (get found-spec "prose"))))) (quasiquote (~specs/not-found :slug (unquote slug)))))))))
(define spreads
(fn (content)
(if (nil? content) '(~geography/spreads-content) content)))
(define explore (fn (slug) (if (nil? slug) (quote (~specs/architecture-content)) (let ((found-spec (find-spec slug))) (if found-spec (let ((data (spec-explore (get found-spec "filename") (get found-spec "title") (get found-spec "desc")))) (if data (quasiquote (~specs-explorer/spec-explorer-content :data (unquote data))) (quasiquote (~specs/not-found :slug (unquote slug))))) (quasiquote (~specs/not-found :slug (unquote slug))))))))
(define marshes
(fn (slug)
(if (nil? slug)
'(~reactive-islands/marshes/reactive-islands-marshes-content)
(case slug
"hypermedia-feeds" '(~reactive-islands/marshes/example-hypermedia-feeds)
"server-signals" '(~reactive-islands/marshes/example-server-signals)
"on-settle" '(~reactive-islands/marshes/example-on-settle)
"signal-triggers" '(~reactive-islands/marshes/example-signal-triggers)
"view-transform" '(~reactive-islands/marshes/example-view-transform)
:else '(~reactive-islands/marshes/reactive-islands-marshes-content)))))
(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 (helper "read-spec-file" (get item "filename")))) items)))
(define isomorphism
(fn (slug)
(if (nil? slug)
'(~plans/isomorphic/plan-isomorphic-content)
(case slug
"bundle-analyzer"
(let ((data (helper "bundle-analyzer-data")))
`(~analyzer/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 (helper "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 (helper "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 (helper "affinity-demo-data")))
`(~affinity-demo/content
:components ,(get data "components")
:page-plans ,(get data "page-plans")))
"optimistic"
(let ((data (helper "optimistic-demo-data")))
`(~optimistic-demo/content
:items ,(get data "items")
:server-time ,(get data "server-time")))
"offline"
(let ((data (helper "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 '(~plans/isomorphic/plan-isomorphic-content)))))
(define bootstrapper (fn (slug) (if (nil? slug) (quote (~specs/bootstrappers-index-content)) (let ((data (helper "bootstrapper-data" slug))) (if (get data "bootstrapper-not-found") (quasiquote (~specs/not-found :slug (unquote slug))) (case slug "self-hosting" (quasiquote (~specs/bootstrapper-self-hosting-content :py-sx-source (unquote (get data "py-sx-source")) :g0-output (unquote (get data "g0-output")) :g1-output (unquote (get data "g1-output")) :defines-matched (unquote (get data "defines-matched")) :defines-total (unquote (get data "defines-total")) :g0-lines (unquote (get data "g0-lines")) :g0-bytes (unquote (get data "g0-bytes")) :verification-status (unquote (get data "verification-status")))) "self-hosting-js" (quasiquote (~specs/bootstrapper-self-hosting-js-content :js-sx-source (unquote (get data "js-sx-source")) :defines-matched (unquote (get data "defines-matched")) :defines-total (unquote (get data "defines-total")) :js-sx-lines (unquote (get data "js-sx-lines")) :verification-status (unquote (get data "verification-status")))) "python" (quasiquote (~specs/bootstrapper-py-content :bootstrapper-source (unquote (get data "bootstrapper-source")) :bootstrapped-output (unquote (get data "bootstrapped-output")))) "page-helpers" (let ((ph-data (helper "page-helpers-demo-data"))) (quasiquote (~page-helpers-demo/content :sf-categories (unquote (get ph-data "sf-categories")) :sf-total (unquote (get ph-data "sf-total")) :sf-ms (unquote (get ph-data "sf-ms")) :ref-sample (unquote (get ph-data "ref-sample")) :ref-ms (unquote (get ph-data "ref-ms")) :attr-result (unquote (get ph-data "attr-result")) :attr-ms (unquote (get ph-data "attr-ms")) :comp-source (unquote (get ph-data "comp-source")) :comp-ms (unquote (get ph-data "comp-ms")) :routing-result (unquote (get ph-data "routing-result")) :routing-ms (unquote (get ph-data "routing-ms")) :server-total-ms (unquote (get ph-data "server-total-ms")) :sf-source (unquote (get ph-data "sf-source")) :attr-detail (unquote (get ph-data "attr-detail")) :req-attrs (unquote (get ph-data "req-attrs")) :attr-keys (unquote (get ph-data "attr-keys"))))) :else (quasiquote (~specs/bootstrapper-js-content :bootstrapper-source (unquote (get data "bootstrapper-source")) :bootstrapped-output (unquote (get data "bootstrapped-output"))))))))))
;; ---------------------------------------------------------------------------
;; Page functions — leaf dispatch to content components
;; ---------------------------------------------------------------------------
(define test (fn (slug) (if (nil? slug) (let ((data (helper "run-modular-tests" "all"))) (quasiquote (~testing/overview-content :server-results (unquote (get data "server-results")) :framework-source (unquote (get data "framework-source")) :eval-source (unquote (get data "eval-source")) :parser-source (unquote (get data "parser-source")) :router-source (unquote (get data "router-source")) :render-source (unquote (get data "render-source")) :deps-source (unquote (get data "deps-source")) :engine-source (unquote (get data "engine-source"))))) (case slug "runners" (quote (~testing/runners-content)) :else (let ((data (helper "run-modular-tests" slug))) (case slug "eval" (quasiquote (~testing/spec-content :spec-name "eval" :spec-title "Evaluator Tests" :spec-desc "81 tests covering the core evaluator and all primitives." :spec-source (unquote (get data "spec-source")) :framework-source (unquote (get data "framework-source")) :server-results (unquote (get data "server-results")))) "parser" (quasiquote (~testing/spec-content :spec-name "parser" :spec-title "Parser Tests" :spec-desc "39 tests covering tokenization and parsing." :spec-source (unquote (get data "spec-source")) :framework-source (unquote (get data "framework-source")) :server-results (unquote (get data "server-results")))) "router" (quasiquote (~testing/spec-content :spec-name "router" :spec-title "Router Tests" :spec-desc "18 tests covering client-side route matching." :spec-source (unquote (get data "spec-source")) :framework-source (unquote (get data "framework-source")) :server-results (unquote (get data "server-results")))) "render" (quasiquote (~testing/spec-content :spec-name "render" :spec-title "Renderer Tests" :spec-desc "23 tests covering HTML rendering." :spec-source (unquote (get data "spec-source")) :framework-source (unquote (get data "framework-source")) :server-results (unquote (get data "server-results")))) "deps" (quasiquote (~testing/spec-content :spec-name "deps" :spec-title "Dependency Analysis Tests" :spec-desc "33 tests covering component dependency analysis." :spec-source (unquote (get data "spec-source")) :framework-source (unquote (get data "framework-source")) :server-results (unquote (get data "server-results")))) "engine" (quasiquote (~testing/spec-content :spec-name "engine" :spec-title "Engine Tests" :spec-desc "37 tests covering engine pure functions." :spec-source (unquote (get data "spec-source")) :framework-source (unquote (get data "framework-source")) :server-results (unquote (get data "server-results")))) "orchestration" (quasiquote (~testing/spec-content :spec-name "orchestration" :spec-title "Orchestration Tests" :spec-desc "17 tests covering orchestration." :spec-source (unquote (get data "spec-source")) :framework-source (unquote (get data "framework-source")) :server-results (unquote (get data "server-results")))) :else (quasiquote (~testing/overview-content :server-results (unquote (get data "server-results"))))))))))
;; Docs (under language)
(define doc
(fn (slug)
(if (nil? slug)
'(~docs-content/docs-introduction-content)
(case slug
"introduction" '(~docs-content/docs-introduction-content)
"getting-started" '(~docs-content/docs-getting-started-content)
"components" '(~docs-content/docs-components-content)
"evaluator" '(~docs-content/docs-evaluator-content)
"primitives"
(let ((data (helper "primitives-data")))
`(~docs-content/docs-primitives-content
:prims (~docs/primitives-tables :primitives ,data)))
"special-forms"
(let ((data (helper "special-forms-data")))
`(~docs-content/docs-special-forms-content
:forms (~docs/special-forms-tables :forms ,data)))
"server-rendering" '(~docs-content/docs-server-rendering-content)
:else '(~docs-content/docs-introduction-content)))))
(define reference (fn (slug) (if (nil? slug) (quote (~examples/reference-index-content)) (let ((data (helper "reference-data" slug))) (case slug "attributes" (quasiquote (~reference/attrs-content :req-table (~docs/attr-table-from-data :title "Request Attributes" :attrs (unquote (get data "req-attrs"))) :beh-table (~docs/attr-table-from-data :title "Behavior Attributes" :attrs (unquote (get data "beh-attrs"))) :uniq-table (~docs/attr-table-from-data :title "Unique to sx" :attrs (unquote (get data "uniq-attrs"))))) "headers" (quasiquote (~reference/headers-content :req-table (~docs/headers-table-from-data :title "Request Headers" :headers (unquote (get data "req-headers"))) :resp-table (~docs/headers-table-from-data :title "Response Headers" :headers (unquote (get data "resp-headers"))))) "events" (quasiquote (~reference/events-content :table (~docs/two-col-table-from-data :intro "sx fires custom DOM events at various points in the request lifecycle." :col1 "Event" :col2 "Description" :items (unquote (get data "events-list"))))) "js-api" (quasiquote (~reference/js-api-content :table (~docs/two-col-table-from-data :intro "The client-side sx.js library exposes a public API for programmatic use." :col1 "Method" :col2 "Description" :items (unquote (get data "js-api-list"))))) :else (quasiquote (~reference/attrs-content :req-table (~docs/attr-table-from-data :title "Request Attributes" :attrs (unquote (get data "req-attrs"))) :beh-table (~docs/attr-table-from-data :title "Behavior Attributes" :attrs (unquote (get data "beh-attrs"))) :uniq-table (~docs/attr-table-from-data :title "Unique to sx" :attrs (unquote (get data "uniq-attrs"))))))))))
;; Specs (under language)
(define spec
(fn (slug)
(if (nil? slug)
'(~specs/architecture-content)
(case slug
"core"
(let ((files (make-spec-files core-spec-items)))
`(~specs/overview-content :spec-title "Core Language" :spec-files ,files))
"adapters"
(let ((files (make-spec-files adapter-spec-items)))
`(~specs/overview-content :spec-title "Adapters" :spec-files ,files))
"browser"
(let ((files (make-spec-files browser-spec-items)))
`(~specs/overview-content :spec-title "Browser Runtime" :spec-files ,files))
"reactive"
(let ((files (make-spec-files reactive-spec-items)))
`(~specs/overview-content :spec-title "Reactive System" :spec-files ,files))
"host"
(let ((files (make-spec-files host-spec-items)))
`(~specs/overview-content :spec-title "Host Interface" :spec-files ,files))
"extensions"
(let ((files (make-spec-files extension-spec-items)))
`(~specs/overview-content :spec-title "Extensions" :spec-files ,files))
:else (let ((found-spec (find-spec slug)))
(if found-spec
(let ((src (helper "read-spec-file" (get found-spec "filename"))))
`(~specs/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")))
`(~specs/not-found :slug ,slug)))))))
(define reference-detail (fn (kind slug) (if (nil? slug) nil (case kind "attributes" (let ((data (helper "attr-detail-data" slug))) (if (get data "attr-not-found") (quasiquote (~reference/attr-not-found :slug (unquote slug))) (quasiquote (~reference/attr-detail-content :title (unquote (get data "attr-title")) :description (unquote (get data "attr-description")) :demo (unquote (get data "attr-demo")) :example-code (unquote (get data "attr-example")) :handler-code (unquote (get data "attr-handler")) :wire-placeholder-id (unquote (get data "attr-wire-id")))))) "headers" (let ((data (helper "header-detail-data" slug))) (if (get data "header-not-found") (quasiquote (~reference/attr-not-found :slug (unquote slug))) (quasiquote (~reference/header-detail-content :title (unquote (get data "header-title")) :direction (unquote (get data "header-direction")) :description (unquote (get data "header-description")) :example-code (unquote (get data "header-example")) :demo (unquote (get data "header-demo")))))) "events" (let ((data (helper "event-detail-data" slug))) (if (get data "event-not-found") (quasiquote (~reference/attr-not-found :slug (unquote slug))) (quasiquote (~reference/event-detail-content :title (unquote (get data "event-title")) :description (unquote (get data "event-description")) :example-code (unquote (get data "event-example")) :demo (unquote (get data "event-demo")))))) :else nil))))
;; Spec explorer (under language → spec)
;; Uses spec-explore from spec-introspect.sx — the spec examines itself.
(define explore
(fn (slug)
(if (nil? slug)
'(~specs/architecture-content)
(let ((found-spec (find-spec slug)))
(if found-spec
(let ((data (spec-explore
(get found-spec "filename")
(get found-spec "title")
(get found-spec "desc"))))
(if data
`(~specs-explorer/spec-explorer-content :data ,data)
`(~specs/not-found :slug ,slug)))
`(~specs/not-found :slug ,slug))))))
(define example (fn (slug) (if (nil? slug) nil (list (slug->component slug "~examples-content/example-" nil "")))))
;; 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 (helper "read-spec-file" (get item "filename"))))
items)))
(define sx-urls (fn (slug) (quote (~sx-urls/urls-content))))
;; Bootstrappers (under language)
(define bootstrapper
(fn (slug)
(if (nil? slug)
'(~specs/bootstrappers-index-content)
(let ((data (helper "bootstrapper-data" slug)))
(if (get data "bootstrapper-not-found")
`(~specs/not-found :slug ,slug)
(case slug
"self-hosting"
`(~specs/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"
`(~specs/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"
`(~specs/bootstrapper-py-content
:bootstrapper-source ,(get data "bootstrapper-source")
:bootstrapped-output ,(get data "bootstrapped-output"))
"page-helpers"
(let ((ph-data (helper "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
`(~specs/bootstrapper-js-content
:bootstrapper-source ,(get data "bootstrapper-source")
:bootstrapped-output ,(get data "bootstrapped-output"))))))))
(define cssx (make-page-fn "~cssx/overview-content" "~cssx/" nil "-content"))
;; Testing (under language)
(define test
(fn (slug)
(if (nil? slug)
(let ((data (helper "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 (helper "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"))))))))
(define protocol (make-page-fn "~protocols/wire-format-content" "~protocols/" nil "-content"))
;; Reference (under geography → hypermedia)
(define reference
(fn (slug)
(if (nil? slug)
'(~examples/reference-index-content)
(let ((data (helper "reference-data" slug)))
(case slug
"attributes" `(~reference/attrs-content
:req-table (~docs/attr-table-from-data :title "Request Attributes" :attrs ,(get data "req-attrs"))
:beh-table (~docs/attr-table-from-data :title "Behavior Attributes" :attrs ,(get data "beh-attrs"))
:uniq-table (~docs/attr-table-from-data :title "Unique to sx" :attrs ,(get data "uniq-attrs")))
"headers" `(~reference/headers-content
:req-table (~docs/headers-table-from-data :title "Request Headers" :headers ,(get data "req-headers"))
:resp-table (~docs/headers-table-from-data :title "Response Headers" :headers ,(get data "resp-headers")))
"events" `(~reference/events-content
:table (~docs/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 (~docs/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 (~docs/attr-table-from-data :title "Request Attributes" :attrs ,(get data "req-attrs"))
:beh-table (~docs/attr-table-from-data :title "Behavior Attributes" :attrs ,(get data "beh-attrs"))
:uniq-table (~docs/attr-table-from-data :title "Unique to sx" :attrs ,(get data "uniq-attrs"))))))))
(define sx-pub (fn (slug) (if (nil? slug) (quote (~sx-pub/overview-content)) nil)))
;; 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 (helper "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 (helper "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 (helper "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))))
(define sx-tools (fn (&key title &rest args) (quasiquote (~sx-tools/overview-content :title (unquote (or title "SX Tools")) (splice-unquote args)))))
;; Examples (under geography → hypermedia)
;; Convention: ~examples-content/example-{slug}
(define example
(fn (slug)
(if (nil? slug) nil
(list (slug->component slug "~examples-content/example-" nil "")))))
(define reactive-runtime (make-page-fn "~reactive-runtime/overview-content" "~reactive-runtime/" nil "-content"))
;; SX URLs (under applications)
(define sx-urls
(fn (slug)
'(~sx-urls/urls-content)))
(define essay (make-page-fn "~essays/index/essays-index-content" "~essays/" "/essay-" ""))
;; CSSX (under applications)
;; Convention: ~cssx/{slug}-content
(define cssx
(make-page-fn "~cssx/overview-content" "~cssx/" nil "-content"))
(define philosophy (fn (slug) (if (nil? slug) (quote (~essays/philosophy-index/content)) (case slug "sx-manifesto" (quote (~essay-sx-manifesto)) "godel-escher-bach" (quote (~essays/godel-escher-bach/essay-godel-escher-bach)) "wittgenstein" (quote (~essays/sx-and-wittgenstein/essay-sx-and-wittgenstein)) "dennett" (quote (~essays/sx-and-dennett/essay-sx-and-dennett)) "existentialism" (quote (~essays/s-existentialism/essay-s-existentialism)) "platonic-sx" (quote (~essays/platonic-sx/essay-platonic-sx)) :else (quote (~essays/philosophy-index/content))))))
;; Protocols (under applications)
;; Convention: ~protocols/{slug}-content
(define protocol
(make-page-fn "~protocols/wire-format-content" "~protocols/" nil "-content"))
;; sx-pub (under applications)
(define sx-pub
(fn (slug)
(if (nil? slug)
'(~sx-pub/overview-content)
nil)))
;; SX Tools (under applications)
(define sx-tools
(fn (slug)
'(~sx-tools/overview-content)))
;; Reactive Runtime (under applications)
;; Convention: ~reactive-runtime/{slug}-content
(define reactive-runtime
(make-page-fn "~reactive-runtime/overview-content" "~reactive-runtime/" nil "-content"))
;; Essays (under etc)
;; Convention: ~essays/{slug}/essay-{slug}
(define essay
(make-page-fn "~essays/index/essays-index-content" "~essays/" "/essay-" ""))
;; Philosophy (under etc)
(define philosophy
(fn (slug)
(if (nil? slug)
'(~essays/philosophy-index/content)
(case slug
"sx-manifesto" '(~essay-sx-manifesto)
"godel-escher-bach" '(~essays/godel-escher-bach/essay-godel-escher-bach)
"wittgenstein" '(~essays/sx-and-wittgenstein/essay-sx-and-wittgenstein)
"dennett" '(~essays/sx-and-dennett/essay-sx-and-dennett)
"existentialism" '(~essays/s-existentialism/essay-s-existentialism)
"platonic-sx" '(~essays/platonic-sx/essay-platonic-sx)
:else '(~essays/philosophy-index/content)))))
;; Plans (under etc)
;; Convention: ~plans/{slug}/plan-{slug}-content
(define plan
(make-page-fn "~plans/index/plans-index-content" "~plans/" "/plan-" "-content"))
(define plan (make-page-fn "~plans/index/plans-index-content" "~plans/" "/plan-" "-content"))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long