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 | [Keyword "else"] -> Bool true
| [Bool true] -> Bool true | [Bool true] -> Bool true
| _ -> Bool false); | _ -> 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 -> register "component?" (fun args ->
match args with [Component _] -> Bool true | [Island _] -> Bool true | _ -> Bool false); match args with [Component _] -> Bool true | [Island _] -> Bool true | _ -> Bool false);
register "lambda-closure" (fun args -> register "lambda-closure" (fun args ->

View File

@@ -1,503 +1,67 @@
;; SX docs page functions — section + page dispatch for GraphSX URL routing. (define slug->component (fn (slug prefix infix suffix) (if infix (make-symbol (str prefix slug infix slug suffix)) (make-symbol (str prefix slug suffix)))))
;;
;; 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 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))))))
;; 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
;; Build a component symbol from a slug and a naming pattern. (define home (fn (content) (if (nil? content) (quote (~docs-content/home-content)) content)))
;; 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)))))
;; Make a simple slug-dispatcher: given a naming convention, returns a function (define language (fn (content) (if (nil? content) nil content)))
;; 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 geography (fn (content) (if (nil? content) (quote (~geography/index-content)) content)))
;; Section functions — structural, pass through content or return index
;; ---------------------------------------------------------------------------
(define home (define applications (fn (content) (if (nil? content) nil content)))
(fn (content)
(if (nil? content) '(~docs-content/home-content) content)))
(define language (define etc (fn (content) (if (nil? content) nil content)))
(fn (content)
(if (nil? content) nil content)))
(define geography (define hypermedia (fn (content) (if (nil? content) nil content)))
(fn (content)
(if (nil? content) '(~geography/index-content) content)))
(define applications (define reactive (fn (content) (if (nil? content) (quote (~reactive-islands/index/reactive-islands-index-content)) content)))
(fn (content)
(if (nil? content) nil content)))
(define etc (define examples (make-page-fn "~reactive-islands/demo/reactive-islands-demo-content" "~reactive-islands/demo/example-" nil ""))
(fn (content)
(if (nil? content) nil content)))
;; 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 (define provide (fn (content) (if (nil? content) (quote (~geography/provide-content)) content)))
(fn (content)
(if (nil? content) nil content)))
(define reactive (define scopes (fn (content) (if (nil? content) (quote (~geography/scopes-content)) content)))
(fn (content)
(if (nil? content)
'(~reactive-islands/index/reactive-islands-index-content)
content)))
;; Convention: ~reactive-islands/demo/example-{slug} (define spreads (fn (content) (if (nil? content) (quote (~geography/spreads-content)) content)))
(define examples
(make-page-fn "~reactive-islands/demo/reactive-islands-demo-content" "~reactive-islands/demo/example-" nil ""))
(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 (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))))))
(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 provide (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))))))
(fn (content)
(if (nil? content) '(~geography/provide-content) content)))
(define scopes (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)))))))))
(fn (content)
(if (nil? content) '(~geography/scopes-content) content)))
(define spreads (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))))))))
(fn (content)
(if (nil? content) '(~geography/spreads-content) content)))
(define marshes (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)))
(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 isomorphism (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"))))))))))
(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 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"))))))))))
;; Page functions — leaf dispatch to content components
;; ---------------------------------------------------------------------------
;; Docs (under language) (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"))))))))))
(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)))))
;; Specs (under language) (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))))
(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)))))))
;; Spec explorer (under language → spec) (define example (fn (slug) (if (nil? slug) nil (list (slug->component slug "~examples-content/example-" nil "")))))
;; 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))))))
;; Helper used by spec — make-spec-files (define sx-urls (fn (slug) (quote (~sx-urls/urls-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)))
;; Bootstrappers (under language) (define cssx (make-page-fn "~cssx/overview-content" "~cssx/" nil "-content"))
(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"))))))))
;; Testing (under language) (define protocol (make-page-fn "~protocols/wire-format-content" "~protocols/" nil "-content"))
(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"))))))))
;; Reference (under geography → hypermedia) (define sx-pub (fn (slug) (if (nil? slug) (quote (~sx-pub/overview-content)) nil)))
(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"))))))))
;; Reference detail pages (under geography → hypermedia → reference) (define sx-tools (fn (&key title &rest args) (quasiquote (~sx-tools/overview-content :title (unquote (or title "SX Tools")) (splice-unquote args)))))
;; 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))))
;; Examples (under geography → hypermedia) (define reactive-runtime (make-page-fn "~reactive-runtime/overview-content" "~reactive-runtime/" nil "-content"))
;; Convention: ~examples-content/example-{slug}
(define example
(fn (slug)
(if (nil? slug) nil
(list (slug->component slug "~examples-content/example-" nil "")))))
;; SX URLs (under applications) (define essay (make-page-fn "~essays/index/essays-index-content" "~essays/" "/essay-" ""))
(define sx-urls
(fn (slug)
'(~sx-urls/urls-content)))
;; CSSX (under applications) (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))))))
;; Convention: ~cssx/{slug}-content
(define cssx
(make-page-fn "~cssx/overview-content" "~cssx/" nil "-content"))
;; Protocols (under applications) (define plan (make-page-fn "~plans/index/plans-index-content" "~plans/" "/plan-" "-content"))
;; 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"))

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long