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:
@@ -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 ->
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user