Adopt Step 7 language features across SX codebase
112 conversions across 19 .sx files using match, let-match, and pipe operators: match (17): type/value dispatch replacing cond/if chains - lib/vm.sx: HO form dispatch (for-each/map/filter/reduce/some/every?) - lib/tree-tools.sx: node-display, node-matches?, rename, count, replace, free-symbols - lib/types.sx: narrow-type, substitute-in-type, infer-type, resolve-type - web/engine.sx: default-trigger, resolve-target, classify-trigger - web/deps.sx: scan-refs-walk, scan-io-refs-walk let-match (89): dict destructuring replacing (get d "key") patterns - shared/page-functions.sx (20), blog/admin.sx (17), pub-api.sx (13) - events/ layouts/page/tickets/entries/forms (27 total) - specs-explorer.sx (7), federation/social.sx (3), lib/ small files (3) -> pipes (6): replacing triple-chained gets in lib/vm.sx - frame-closure → closure-code → code-bytecode chains Also: lib/vm.sx accessor upgrades (get vm "sp" → vm-sp vm throughout) 2650/2650 tests pass, zero regressions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -9,71 +9,89 @@
|
||||
;; Actor
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-actor
|
||||
(defhandler
|
||||
pub-actor
|
||||
:path "/pub/actor"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((actor (helper "pub-actor-data")))
|
||||
(let-match
|
||||
{:domain domain :summary summary :display-name display-name :public-key-pem public-key-pem}
|
||||
(helper "pub-actor-data")
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str
|
||||
"(SxActor"
|
||||
"\n :id \"https://" (get actor "domain") "/pub/actor\""
|
||||
"\n :id \"https://"
|
||||
domain
|
||||
"/pub/actor\""
|
||||
"\n :type \"SxPublisher\""
|
||||
"\n :name \"" (get actor "display-name") "\""
|
||||
"\n :summary \"" (get actor "summary") "\""
|
||||
"\n :name \""
|
||||
display-name
|
||||
"\""
|
||||
"\n :summary \""
|
||||
summary
|
||||
"\""
|
||||
"\n :inbox \"/pub/inbox\""
|
||||
"\n :outbox \"/pub/outbox\""
|
||||
"\n :followers \"/pub/followers\""
|
||||
"\n :following \"/pub/following\""
|
||||
"\n :public-key-pem \"" (get actor "public-key-pem") "\")"))))
|
||||
"\n :public-key-pem \""
|
||||
public-key-pem
|
||||
"\")"))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Webfinger
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-webfinger
|
||||
(defhandler
|
||||
pub-webfinger
|
||||
:path "/pub/webfinger"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((resource (helper "request-arg" "resource" ""))
|
||||
(actor (helper "pub-actor-data")))
|
||||
(let ((expected (str "acct:" (get actor "preferred-username") "@" (get actor "domain"))))
|
||||
(if (!= resource expected)
|
||||
(do
|
||||
(set-response-status 404)
|
||||
(str "(Error :message \"Resource not found\")"))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str
|
||||
"(SxWebfinger"
|
||||
"\n :subject \"" expected "\""
|
||||
"\n :actor \"https://" (get actor "domain") "/pub/actor\""
|
||||
"\n :type \"SxPublisher\")"))))))
|
||||
(let
|
||||
((resource (helper "request-arg" "resource" "")))
|
||||
(let-match
|
||||
{:domain domain :preferred-username preferred-username}
|
||||
(helper "pub-actor-data")
|
||||
(let
|
||||
((expected (str "acct:" preferred-username "@" domain)))
|
||||
(if
|
||||
(!= resource expected)
|
||||
(do
|
||||
(set-response-status 404)
|
||||
(str "(Error :message \"Resource not found\")"))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str
|
||||
"(SxWebfinger"
|
||||
"\n :subject \""
|
||||
expected
|
||||
"\""
|
||||
"\n :actor \"https://"
|
||||
domain
|
||||
"/pub/actor\""
|
||||
"\n :type \"SxPublisher\")")))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Collections
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-collections
|
||||
(defhandler
|
||||
pub-collections
|
||||
:path "/pub/collections"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((collections (helper "pub-collections-data")))
|
||||
(let
|
||||
((collections (helper "pub-collections-data")))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(let ((items (map (fn (c)
|
||||
(str "\n (SxCollection"
|
||||
" :slug \"" (get c "slug") "\""
|
||||
" :name \"" (get c "name") "\""
|
||||
" :description \"" (get c "description") "\""
|
||||
" :href \"/pub/" (get c "slug") "\")"))
|
||||
collections)))
|
||||
(let
|
||||
((items (map (fn (c) (let-match {:description description :slug slug :name name} c (str "\n (SxCollection" " :slug \"" slug "\"" " :name \"" name "\"" " :description \"" description "\"" " :href \"/pub/" slug "\")"))) collections)))
|
||||
(str "(SxCollections" (join "" items) ")")))))
|
||||
|
||||
|
||||
@@ -81,21 +99,33 @@
|
||||
;; Status
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-status
|
||||
(defhandler
|
||||
pub-status
|
||||
:path "/pub/status"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((status (helper "pub-status-data")))
|
||||
(let-match
|
||||
{:db db :domain domain :healthy healthy :ipfs ipfs :actor actor}
|
||||
(helper "pub-status-data")
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str
|
||||
"(SxPubStatus"
|
||||
"\n :healthy " (get status "healthy")
|
||||
"\n :db \"" (get status "db") "\""
|
||||
"\n :ipfs \"" (get status "ipfs") "\""
|
||||
"\n :actor \"" (get status "actor") "\""
|
||||
"\n :domain \"" (or (get status "domain") "unknown") "\")"))))
|
||||
"\n :healthy "
|
||||
healthy
|
||||
"\n :db \""
|
||||
db
|
||||
"\""
|
||||
"\n :ipfs \""
|
||||
ipfs
|
||||
"\""
|
||||
"\n :actor \""
|
||||
actor
|
||||
"\""
|
||||
"\n :domain \""
|
||||
(or domain "unknown")
|
||||
"\")"))))
|
||||
|
||||
|
||||
;; ==========================================================================
|
||||
@@ -107,72 +137,100 @@
|
||||
;; Publish
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-publish
|
||||
(defhandler
|
||||
pub-publish
|
||||
:path "/pub/publish"
|
||||
:method :post
|
||||
:csrf false
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((collection (helper "request-form" "collection" ""))
|
||||
(slug (helper "request-form" "slug" ""))
|
||||
(content (helper "request-form" "content" ""))
|
||||
(title (helper "request-form" "title" ""))
|
||||
(summary (helper "request-form" "summary" "")))
|
||||
(if (or (= collection "") (= slug "") (= content ""))
|
||||
(let
|
||||
((collection (helper "request-form" "collection" ""))
|
||||
(slug (helper "request-form" "slug" ""))
|
||||
(content (helper "request-form" "content" ""))
|
||||
(title (helper "request-form" "title" ""))
|
||||
(summary (helper "request-form" "summary" "")))
|
||||
(if
|
||||
(or (= collection "") (= slug "") (= content ""))
|
||||
(do
|
||||
(set-response-status 400)
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
"(Error :message \"Missing collection, slug, or content\")")
|
||||
(let ((result (helper "pub-publish" collection slug content title summary)))
|
||||
(if (get result "error")
|
||||
(let
|
||||
((result (helper "pub-publish" collection slug content title summary)))
|
||||
(if
|
||||
(get result "error")
|
||||
(do
|
||||
(set-response-status 500)
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str "(Error :message \"" (get result "error") "\")"))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str
|
||||
"(Published"
|
||||
"\n :path \"" (get result "path") "\""
|
||||
"\n :cid \"" (get result "cid") "\""
|
||||
"\n :hash \"" (get result "hash") "\""
|
||||
"\n :size " (get result "size")
|
||||
"\n :collection \"" (get result "collection") "\""
|
||||
"\n :slug \"" (get result "slug") "\""
|
||||
"\n :title \"" (get result "title") "\")")))))))
|
||||
(let-match
|
||||
{:cid cid :hash hash :size size :title title :path path :slug slug :collection collection}
|
||||
result
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str
|
||||
"(Published"
|
||||
"\n :path \""
|
||||
path
|
||||
"\""
|
||||
"\n :cid \""
|
||||
cid
|
||||
"\""
|
||||
"\n :hash \""
|
||||
hash
|
||||
"\""
|
||||
"\n :size "
|
||||
size
|
||||
"\n :collection \""
|
||||
collection
|
||||
"\""
|
||||
"\n :slug \""
|
||||
slug
|
||||
"\""
|
||||
"\n :title \""
|
||||
title
|
||||
"\")"))))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Browse collection
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-browse-collection
|
||||
(defhandler
|
||||
pub-browse-collection
|
||||
:path "/pub/browse/<collection_slug>"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key collection_slug)
|
||||
(let ((data (helper "pub-collection-items" collection_slug)))
|
||||
(if (get data "error")
|
||||
(let
|
||||
((data (helper "pub-collection-items" collection_slug)))
|
||||
(if
|
||||
(get data "error")
|
||||
(do
|
||||
(set-response-status 404)
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(str "(Error :message \"" (get data "error") "\")"))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(let ((items (map (fn (d)
|
||||
(str "\n (SxDocument"
|
||||
" :slug \"" (get d "slug") "\""
|
||||
" :title \"" (get d "title") "\""
|
||||
" :summary \"" (get d "summary") "\""
|
||||
" :cid \"" (get d "cid") "\""
|
||||
" :size " (get d "size") ")"))
|
||||
(get data "items"))))
|
||||
(str
|
||||
"(SxCollection"
|
||||
"\n :slug \"" (get data "collection") "\""
|
||||
"\n :name \"" (get data "name") "\""
|
||||
"\n :description \"" (get data "description") "\""
|
||||
(join "" items) ")"))))))
|
||||
(let-match
|
||||
{:description description :items items-data :collection collection :name name}
|
||||
data
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(let
|
||||
((items (map (fn (d) (let-match {:cid cid :size size :summary summary :title title :slug slug} d (str "\n (SxDocument" " :slug \"" slug "\"" " :title \"" title "\"" " :summary \"" summary "\"" " :cid \"" cid "\"" " :size " size ")"))) items-data)))
|
||||
(str
|
||||
"(SxCollection"
|
||||
"\n :slug \""
|
||||
collection
|
||||
"\""
|
||||
"\n :name \""
|
||||
name
|
||||
"\""
|
||||
"\n :description \""
|
||||
description
|
||||
"\""
|
||||
(join "" items)
|
||||
")")))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -226,26 +284,30 @@
|
||||
;; Outbox
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-outbox
|
||||
(defhandler
|
||||
pub-outbox
|
||||
:path "/pub/outbox"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((page (helper "request-arg" "page" ""))
|
||||
(data (helper "pub-outbox-data" page)))
|
||||
(let
|
||||
((page (helper "request-arg" "page" ""))
|
||||
(data (helper "pub-outbox-data" page)))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(let ((items (map (fn (a)
|
||||
(str "\n (" (get a "type")
|
||||
" :object-type \"" (get a "object-type") "\""
|
||||
" :published \"" (get a "published") "\""
|
||||
" :cid \"" (get a "cid") "\")"))
|
||||
(get data "items"))))
|
||||
(str
|
||||
"(SxOutbox"
|
||||
"\n :total " (get data "total")
|
||||
"\n :page " (get data "page")
|
||||
(join "" items) ")")))))
|
||||
(let-match
|
||||
{:total total :page page :items items-data}
|
||||
data
|
||||
(let
|
||||
((items (map (fn (a) (let-match {:cid cid :type type :object-type object-type :published published} a (str "\n (" type " :object-type \"" object-type "\"" " :published \"" published "\"" " :cid \"" cid "\")"))) items-data)))
|
||||
(str
|
||||
"(SxOutbox"
|
||||
"\n :total "
|
||||
total
|
||||
"\n :page "
|
||||
page
|
||||
(join "" items)
|
||||
")"))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
@@ -275,48 +337,59 @@
|
||||
;; Follow a remote server
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-follow
|
||||
(defhandler
|
||||
pub-follow
|
||||
:path "/pub/follow"
|
||||
:method :post
|
||||
:csrf false
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((actor-url (helper "request-form" "actor_url" "")))
|
||||
(if (= actor-url "")
|
||||
(let
|
||||
((actor-url (helper "request-form" "actor_url" "")))
|
||||
(if
|
||||
(= actor-url "")
|
||||
(do
|
||||
(set-response-status 400)
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
"(Error :message \"Missing actor_url\")")
|
||||
(let ((result (helper "pub-follow-remote" actor-url)))
|
||||
(let
|
||||
((result (helper "pub-follow-remote" actor-url)))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(if (get result "error")
|
||||
(if
|
||||
(get result "error")
|
||||
(do
|
||||
(set-response-status 502)
|
||||
(str "(Error :message \"" (get result "error") "\")"))
|
||||
(str
|
||||
"(FollowSent"
|
||||
"\n :actor-url \"" (get result "actor-url") "\""
|
||||
"\n :status \"" (get result "status") "\")")))))))
|
||||
(let-match
|
||||
{:status status :actor-url actor-url}
|
||||
result
|
||||
(str
|
||||
"(FollowSent"
|
||||
"\n :actor-url \""
|
||||
actor-url
|
||||
"\""
|
||||
"\n :status \""
|
||||
status
|
||||
"\")"))))))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Followers
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-followers
|
||||
(defhandler
|
||||
pub-followers
|
||||
:path "/pub/followers"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((data (helper "pub-followers-data")))
|
||||
(let
|
||||
((data (helper "pub-followers-data")))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(let ((items (map (fn (f)
|
||||
(str "\n (SxFollower"
|
||||
" :acct \"" (get f "acct") "\""
|
||||
" :actor-url \"" (get f "actor-url") "\")"))
|
||||
data)))
|
||||
(let
|
||||
((items (map (fn (f) (let-match {:actor-url actor-url :acct acct} f (str "\n (SxFollower" " :acct \"" acct "\"" " :actor-url \"" actor-url "\")"))) data)))
|
||||
(str "(SxFollowers" (join "" items) ")")))))
|
||||
|
||||
|
||||
@@ -348,48 +421,80 @@
|
||||
;; Anchor pending activities
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-anchor
|
||||
(defhandler
|
||||
pub-anchor
|
||||
:path "/pub/anchor"
|
||||
:method :post
|
||||
:csrf false
|
||||
:returns "element"
|
||||
(&key)
|
||||
(let ((result (helper "pub-anchor-pending")))
|
||||
(let-match
|
||||
{:tree-cid tree-cid :status status :count count :ots-proof-cid ots-proof-cid :merkle-root merkle-root}
|
||||
(helper "pub-anchor-pending")
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(if (= (get result "status") "nothing-to-anchor")
|
||||
(if
|
||||
(= status "nothing-to-anchor")
|
||||
"(Anchor :status \"nothing-to-anchor\" :count 0)"
|
||||
(str
|
||||
"(Anchor"
|
||||
"\n :status \"" (get result "status") "\""
|
||||
"\n :count " (get result "count")
|
||||
"\n :merkle-root \"" (get result "merkle-root") "\""
|
||||
"\n :tree-cid \"" (get result "tree-cid") "\""
|
||||
"\n :ots-proof-cid \"" (get result "ots-proof-cid") "\")")))))
|
||||
"\n :status \""
|
||||
status
|
||||
"\""
|
||||
"\n :count "
|
||||
count
|
||||
"\n :merkle-root \""
|
||||
merkle-root
|
||||
"\""
|
||||
"\n :tree-cid \""
|
||||
tree-cid
|
||||
"\""
|
||||
"\n :ots-proof-cid \""
|
||||
ots-proof-cid
|
||||
"\")")))))
|
||||
|
||||
|
||||
;; --------------------------------------------------------------------------
|
||||
;; Verify a CID's anchor
|
||||
;; --------------------------------------------------------------------------
|
||||
|
||||
(defhandler pub-verify
|
||||
(defhandler
|
||||
pub-verify
|
||||
:path "/pub/verify/<cid>"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key cid)
|
||||
(let ((data (helper "pub-verify-anchor" cid)))
|
||||
(let
|
||||
((data (helper "pub-verify-anchor" cid)))
|
||||
(do
|
||||
(set-response-header "Content-Type" "text/sx; charset=utf-8")
|
||||
(if (get data "error")
|
||||
(if
|
||||
(get data "error")
|
||||
(do
|
||||
(set-response-status 404)
|
||||
(str "(Error :message \"" (get data "error") "\")"))
|
||||
(str
|
||||
"(AnchorVerification"
|
||||
"\n :cid \"" (get data "cid") "\""
|
||||
"\n :status \"" (get data "status") "\""
|
||||
"\n :verified " (get data "verified")
|
||||
"\n :merkle-root \"" (get data "merkle-root") "\""
|
||||
"\n :tree-cid \"" (get data "tree-cid") "\""
|
||||
"\n :ots-proof-cid \"" (get data "ots-proof-cid") "\""
|
||||
"\n :published \"" (get data "published") "\")")))))
|
||||
(let-match
|
||||
{:cid cid* :tree-cid tree-cid :status status :verified verified :ots-proof-cid ots-proof-cid :merkle-root merkle-root :published published}
|
||||
data
|
||||
(str
|
||||
"(AnchorVerification"
|
||||
"\n :cid \""
|
||||
cid*
|
||||
"\""
|
||||
"\n :status \""
|
||||
status
|
||||
"\""
|
||||
"\n :verified "
|
||||
verified
|
||||
"\n :merkle-root \""
|
||||
merkle-root
|
||||
"\""
|
||||
"\n :tree-cid \""
|
||||
tree-cid
|
||||
"\""
|
||||
"\n :ots-proof-cid \""
|
||||
ots-proof-cid
|
||||
"\""
|
||||
"\n :published \""
|
||||
published
|
||||
"\")"))))))
|
||||
|
||||
@@ -2,25 +2,27 @@
|
||||
~specs-explorer/spec-explorer-content
|
||||
(&key data)
|
||||
:affinity :server
|
||||
(~docs/page
|
||||
:title (str (get data "title") " — Explorer")
|
||||
(~specs-explorer/spec-explorer-header
|
||||
:filename (get data "filename")
|
||||
:title (get data "title")
|
||||
:desc (get data "desc")
|
||||
:slug (replace (get data "filename") ".sx" ""))
|
||||
(~specs-explorer/spec-explorer-stats :stats (get data "stats"))
|
||||
(map
|
||||
(fn
|
||||
(section)
|
||||
(~specs-explorer/spec-explorer-section
|
||||
:section section
|
||||
:filename (get data "filename")))
|
||||
(get data "sections"))
|
||||
(when
|
||||
(not (empty? (get data "platform-interface")))
|
||||
(~specs-explorer/spec-platform-interface
|
||||
:items (get data "platform-interface")))))
|
||||
(let-match
|
||||
{:stats stats :desc desc :title title :filename filename :platform-interface platform-interface :sections sections}
|
||||
data
|
||||
(~docs/page
|
||||
:title (str title " — Explorer")
|
||||
(~specs-explorer/spec-explorer-header
|
||||
:filename filename
|
||||
:title title
|
||||
:desc desc
|
||||
:slug (replace filename ".sx" ""))
|
||||
(~specs-explorer/spec-explorer-stats :stats stats)
|
||||
(map
|
||||
(fn
|
||||
(section)
|
||||
(~specs-explorer/spec-explorer-section
|
||||
:section section
|
||||
:filename filename))
|
||||
sections)
|
||||
(when
|
||||
(not (empty? platform-interface))
|
||||
(~specs-explorer/spec-platform-interface :items platform-interface)))))
|
||||
|
||||
(defcomp
|
||||
~specs-explorer/spec-explorer-header
|
||||
@@ -46,80 +48,91 @@
|
||||
(defcomp
|
||||
~specs-explorer/spec-explorer-stats
|
||||
(&key stats)
|
||||
(div
|
||||
(~tw :tokens "flex flex-wrap gap-2 mb-6 text-xs")
|
||||
(span
|
||||
(~tw :tokens "bg-stone-100 text-stone-600 px-2 py-0.5 rounded font-medium")
|
||||
(str (get stats "total-defines") " defines"))
|
||||
(when
|
||||
(> (get stats "pure-count") 0)
|
||||
(let-match
|
||||
{:lines lines :io-count io-count :render-count render-count :pure-count pure-count :mutation-count mutation-count :test-total test-total :total-defines total-defines}
|
||||
stats
|
||||
(div
|
||||
(~tw :tokens "flex flex-wrap gap-2 mb-6 text-xs")
|
||||
(span
|
||||
(~tw :tokens "bg-green-100 text-green-700 px-2 py-0.5 rounded")
|
||||
(str (get stats "pure-count") " pure")))
|
||||
(when
|
||||
(> (get stats "mutation-count") 0)
|
||||
(~tw
|
||||
:tokens "bg-stone-100 text-stone-600 px-2 py-0.5 rounded font-medium")
|
||||
(str total-defines " defines"))
|
||||
(when
|
||||
(> pure-count 0)
|
||||
(span
|
||||
(~tw :tokens "bg-green-100 text-green-700 px-2 py-0.5 rounded")
|
||||
(str pure-count " pure")))
|
||||
(when
|
||||
(> mutation-count 0)
|
||||
(span
|
||||
(~tw :tokens "bg-amber-100 text-amber-700 px-2 py-0.5 rounded")
|
||||
(str mutation-count " mutation")))
|
||||
(when
|
||||
(> io-count 0)
|
||||
(span
|
||||
(~tw :tokens "bg-orange-100 text-orange-700 px-2 py-0.5 rounded")
|
||||
(str io-count " io")))
|
||||
(when
|
||||
(> render-count 0)
|
||||
(span
|
||||
(~tw :tokens "bg-sky-100 text-sky-700 px-2 py-0.5 rounded")
|
||||
(str render-count " render")))
|
||||
(when
|
||||
(> test-total 0)
|
||||
(span
|
||||
(~tw :tokens "bg-violet-100 text-violet-700 px-2 py-0.5 rounded")
|
||||
(str test-total " tests")))
|
||||
(span
|
||||
(~tw :tokens "bg-amber-100 text-amber-700 px-2 py-0.5 rounded")
|
||||
(str (get stats "mutation-count") " mutation")))
|
||||
(when
|
||||
(> (get stats "io-count") 0)
|
||||
(span
|
||||
(~tw :tokens "bg-orange-100 text-orange-700 px-2 py-0.5 rounded")
|
||||
(str (get stats "io-count") " io")))
|
||||
(when
|
||||
(> (get stats "render-count") 0)
|
||||
(span
|
||||
(~tw :tokens "bg-sky-100 text-sky-700 px-2 py-0.5 rounded")
|
||||
(str (get stats "render-count") " render")))
|
||||
(when
|
||||
(> (get stats "test-total") 0)
|
||||
(span
|
||||
(~tw :tokens "bg-violet-100 text-violet-700 px-2 py-0.5 rounded")
|
||||
(str (get stats "test-total") " tests")))
|
||||
(span
|
||||
(~tw :tokens "bg-stone-100 text-stone-500 px-2 py-0.5 rounded")
|
||||
(str (get stats "lines") " lines"))))
|
||||
(~tw :tokens "bg-stone-100 text-stone-500 px-2 py-0.5 rounded")
|
||||
(str lines " lines")))))
|
||||
|
||||
(defcomp
|
||||
~specs-explorer/spec-explorer-section
|
||||
(&key section filename)
|
||||
(div
|
||||
(~tw :tokens "mb-6")
|
||||
(h2
|
||||
(~tw :tokens "text-base font-semibold text-stone-600 mb-2 border-b border-stone-200 pb-1")
|
||||
:id (replace (lower (get section "title")) " " "-")
|
||||
(get section "title"))
|
||||
(when
|
||||
(get section "comment")
|
||||
(p (~tw :tokens "text-sm text-stone-500 mb-2") (get section "comment")))
|
||||
(let-match
|
||||
{:defines defines :title title :comment comment}
|
||||
section
|
||||
(div
|
||||
(~tw :tokens "space-y-0.5")
|
||||
(map
|
||||
(fn
|
||||
(d)
|
||||
(~specs-explorer/spec-explorer-define :d d :filename filename))
|
||||
(get section "defines")))))
|
||||
(~tw :tokens "mb-6")
|
||||
(h2
|
||||
(~tw
|
||||
:tokens "text-base font-semibold text-stone-600 mb-2 border-b border-stone-200 pb-1")
|
||||
:id (replace (lower title) " " "-")
|
||||
title)
|
||||
(when comment (p (~tw :tokens "text-sm text-stone-500 mb-2") comment))
|
||||
(div
|
||||
(~tw :tokens "space-y-0.5")
|
||||
(map
|
||||
(fn
|
||||
(d)
|
||||
(~specs-explorer/spec-explorer-define :d d :filename filename))
|
||||
defines)))))
|
||||
|
||||
(defcomp
|
||||
~specs-explorer/spec-explorer-define
|
||||
(&key d filename)
|
||||
(div
|
||||
(~tw :tokens "flex items-center gap-2 py-1.5 px-2 rounded hover:bg-stone-50 cursor-pointer group")
|
||||
:id (str "fn-" (get d "name"))
|
||||
:sx-get (str
|
||||
"/sx/(language.(spec.(explore."
|
||||
(replace filename ".sx" "")
|
||||
"."
|
||||
(get d "name")
|
||||
")))")
|
||||
:sx-target "#sx-content"
|
||||
:sx-select "#sx-content"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-push-url "true"
|
||||
(span
|
||||
(~tw :tokens "font-mono text-sm font-medium text-stone-800 group-hover:text-violet-700")
|
||||
(get d "name"))
|
||||
(span (~tw :tokens "text-xs text-stone-400") (get d "kind"))))
|
||||
(let-match
|
||||
{:kind kind :name name}
|
||||
d
|
||||
(div
|
||||
(~tw
|
||||
:tokens "flex items-center gap-2 py-1.5 px-2 rounded hover:bg-stone-50 cursor-pointer group")
|
||||
:id (str "fn-" name)
|
||||
:sx-get (str
|
||||
"/sx/(language.(spec.(explore."
|
||||
(replace filename ".sx" "")
|
||||
"."
|
||||
name
|
||||
")))")
|
||||
:sx-target "#sx-content"
|
||||
:sx-select "#sx-content"
|
||||
:sx-swap "innerHTML"
|
||||
:sx-push-url "true"
|
||||
(span
|
||||
(~tw
|
||||
:tokens "font-mono text-sm font-medium text-stone-800 group-hover:text-violet-700")
|
||||
name)
|
||||
(span (~tw :tokens "text-xs text-stone-400") kind))))
|
||||
|
||||
(defcomp
|
||||
~specs-explorer/spec-explorer-define-detail
|
||||
@@ -144,33 +157,39 @@
|
||||
:sx-swap "innerHTML"
|
||||
:sx-push-url "true"
|
||||
(str "← Back to " (replace filename ".sx" ""))))
|
||||
(div
|
||||
(~tw :tokens "rounded border border-violet-200 bg-violet-50/30 p-4")
|
||||
(let-match
|
||||
{:kind kind :effects effects :params params :source source :name name}
|
||||
d
|
||||
(div
|
||||
(~tw :tokens "flex items-center gap-2 flex-wrap mb-3")
|
||||
(span
|
||||
(~tw :tokens "font-mono text-lg font-semibold text-stone-800")
|
||||
(get d "name"))
|
||||
(span (~tw :tokens "text-xs text-stone-400") (get d "kind"))
|
||||
(if
|
||||
(empty? (get d "effects"))
|
||||
(~tw :tokens "rounded border border-violet-200 bg-violet-50/30 p-4")
|
||||
(div
|
||||
(~tw :tokens "flex items-center gap-2 flex-wrap mb-3")
|
||||
(span
|
||||
(~tw :tokens "text-xs px-1.5 py-0.5 rounded bg-green-100 text-green-700")
|
||||
"pure")
|
||||
(map
|
||||
(fn (eff) (~specs-explorer/spec-effect-badge :effect eff))
|
||||
(get d "effects"))))
|
||||
(when
|
||||
(not (empty? (get d "params")))
|
||||
(~specs-explorer/spec-param-list :params (get d "params")))
|
||||
(details
|
||||
:open "true"
|
||||
(summary
|
||||
(~tw :tokens "px-3 py-1.5 bg-stone-50 text-xs font-medium text-stone-600 cursor-pointer select-none mt-3 rounded")
|
||||
"SX Source")
|
||||
(pre
|
||||
(~tw :tokens "text-xs p-3 overflow-x-auto bg-white rounded mt-1 border border-stone-200")
|
||||
(code (~tw :tokens "language-sx") (get d "source")))))))
|
||||
(~tw :tokens "font-mono text-lg font-semibold text-stone-800")
|
||||
name)
|
||||
(span (~tw :tokens "text-xs text-stone-400") kind)
|
||||
(if
|
||||
(empty? effects)
|
||||
(span
|
||||
(~tw
|
||||
:tokens "text-xs px-1.5 py-0.5 rounded bg-green-100 text-green-700")
|
||||
"pure")
|
||||
(map
|
||||
(fn (eff) (~specs-explorer/spec-effect-badge :effect eff))
|
||||
effects)))
|
||||
(when
|
||||
(not (empty? params))
|
||||
(~specs-explorer/spec-param-list :params params))
|
||||
(details
|
||||
:open "true"
|
||||
(summary
|
||||
(~tw
|
||||
:tokens "px-3 py-1.5 bg-stone-50 text-xs font-medium text-stone-600 cursor-pointer select-none mt-3 rounded")
|
||||
"SX Source")
|
||||
(pre
|
||||
(~tw
|
||||
:tokens "text-xs p-3 overflow-x-auto bg-white rounded mt-1 border border-stone-200")
|
||||
(code (~tw :tokens "language-sx") source)))))))
|
||||
|
||||
(defcomp
|
||||
~specs-explorer/spec-effect-badge
|
||||
@@ -197,13 +216,15 @@
|
||||
(map
|
||||
(fn
|
||||
(p)
|
||||
(let
|
||||
((name (get p "name")) (typ (get p "type")))
|
||||
(let-match
|
||||
{:type typ :name name}
|
||||
p
|
||||
(if
|
||||
(or (= name "&rest") (= name "&key"))
|
||||
(span (~tw :tokens "text-xs font-mono text-violet-500") name)
|
||||
(span
|
||||
(~tw :tokens "text-xs font-mono px-1 py-0.5 rounded bg-stone-50 border border-stone-200")
|
||||
(~tw
|
||||
:tokens "text-xs font-mono px-1 py-0.5 rounded bg-stone-50 border border-stone-200")
|
||||
(if
|
||||
typ
|
||||
(<>
|
||||
@@ -300,7 +321,8 @@
|
||||
(div
|
||||
(~tw :tokens "mt-8")
|
||||
(h2
|
||||
(~tw :tokens "text-lg font-semibold text-stone-700 border-b border-stone-200 pb-1 mb-3")
|
||||
(~tw
|
||||
:tokens "text-lg font-semibold text-stone-700 border-b border-stone-200 pb-1 mb-3")
|
||||
"Platform Interface")
|
||||
(p
|
||||
(~tw :tokens "text-sm text-stone-500 mb-3")
|
||||
@@ -314,22 +336,29 @@
|
||||
(~tw :tokens "border-b border-stone-200 bg-stone-50")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Name")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Params")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Returns")
|
||||
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Description")))
|
||||
(th
|
||||
(~tw :tokens "px-3 py-2 font-medium text-stone-600")
|
||||
"Returns")
|
||||
(th
|
||||
(~tw :tokens "px-3 py-2 font-medium text-stone-600")
|
||||
"Description")))
|
||||
(tbody
|
||||
(map
|
||||
(fn
|
||||
(item)
|
||||
(tr
|
||||
(~tw :tokens "border-b border-stone-100")
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700")
|
||||
(get item "name"))
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2 font-mono text-xs text-stone-500")
|
||||
(get item "params"))
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2 font-mono text-xs text-stone-500")
|
||||
(get item "returns"))
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-600") (get item "doc"))))
|
||||
(let-match
|
||||
{:doc doc :params params :returns returns :name name}
|
||||
item
|
||||
(tr
|
||||
(~tw :tokens "border-b border-stone-100")
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2 font-mono text-sm text-violet-700")
|
||||
name)
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2 font-mono text-xs text-stone-500")
|
||||
params)
|
||||
(td
|
||||
(~tw :tokens "px-3 py-2 font-mono text-xs text-stone-500")
|
||||
returns)
|
||||
(td (~tw :tokens "px-3 py-2 text-stone-600") doc))))
|
||||
items))))))
|
||||
|
||||
Reference in New Issue
Block a user