HS parser: fix number+comparison keyword collision, eval-hs uses hs-compile
Parser: skip unit suffix when next ident is a comparison keyword (starts, ends, contains, matches, is, does, in, precedes, follows). Fixes "123 starts with '12'" returning "123starts" instead of true. eval-hs: use hs-compile directly instead of hs-to-sx-from-source with "return " prefix, which was causing the parser to consume the comparison as a string suffix. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
24
sx/sx/handlers/graphql-api.sx
Normal file
24
sx/sx/handlers/graphql-api.sx
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
;; GraphQL playground API handler — returns raw text for innerHTML injection
|
||||
|
||||
(defhandler
|
||||
gql-parse-demo
|
||||
:path "/sx/(applications.(graphql.(api.parse-demo)))"
|
||||
:method :get
|
||||
:returns "text"
|
||||
(&key source)
|
||||
(if
|
||||
(or (nil? source) (empty? source))
|
||||
"<p class=\"text-sm text-gray-400 italic\">Enter a GraphQL query and click Parse.</p>"
|
||||
(let
|
||||
((doc (gql-parse source)))
|
||||
(str
|
||||
"<div class=\"space-y-4\">"
|
||||
"<div><h4 class=\"text-xs font-semibold uppercase tracking-wider text-gray-500 mb-2\">AST</h4>"
|
||||
"<pre class=\"bg-gray-900 text-green-400 p-4 rounded-lg text-sm overflow-x-auto\">"
|
||||
(escape (sx-serialize doc))
|
||||
"</pre></div>"
|
||||
"<div><h4 class=\"text-xs font-semibold uppercase tracking-wider text-gray-500 mb-2\">Serialized</h4>"
|
||||
"<pre class=\"bg-gray-900 text-amber-400 p-4 rounded-lg text-sm overflow-x-auto\">"
|
||||
(escape (gql-serialize doc))
|
||||
"</pre></div></div>"))))
|
||||
138
sx/sx/handlers/htmx-api.sx
Normal file
138
sx/sx/handlers/htmx-api.sx
Normal file
@@ -0,0 +1,138 @@
|
||||
;; htmx demo API handlers — return HTML fragments for hx-* demos
|
||||
|
||||
;; Click to load
|
||||
(defhandler
|
||||
ex-click
|
||||
:path "/sx/(applications.(htmx.(api.click)))"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(div
|
||||
(~tw :tokens "space-y-2")
|
||||
(p (~tw :tokens "text-stone-800 font-medium") "Content loaded!")
|
||||
(p
|
||||
(~tw :tokens "text-stone-500 text-sm")
|
||||
"Fetched from the server via hx-get")))
|
||||
|
||||
;; Active search
|
||||
(defhandler
|
||||
ex-search
|
||||
:path "/sx/(applications.(htmx.(api.search)))"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key q)
|
||||
(let
|
||||
((query (or q "")))
|
||||
(let
|
||||
((items (list {:desc "GET request" :name "hx-get"} {:desc "POST request" :name "hx-post"} {:desc "Swap strategy" :name "hx-swap"} {:desc "Target element" :name "hx-target"} {:desc "Event trigger" :name "hx-trigger"} {:desc "Confirm dialog" :name "hx-confirm"} {:desc "Progressive enhancement" :name "hx-boost"} {:desc "CSS selector filter" :name "hx-select"})))
|
||||
(let
|
||||
((filtered (if (= query "") (list) (filter (fn (item) (contains? (downcase (get item :name)) (downcase query))) items))))
|
||||
(if
|
||||
(empty? filtered)
|
||||
(p
|
||||
(~tw :tokens "text-gray-400 italic py-2")
|
||||
(str "No results for \"" query "\""))
|
||||
(ul
|
||||
(~tw :tokens "divide-y divide-gray-100")
|
||||
(map
|
||||
(fn
|
||||
(item)
|
||||
(li
|
||||
(~tw :tokens "py-2 px-1")
|
||||
(span
|
||||
(~tw :tokens "font-medium text-gray-800")
|
||||
(get item :name))
|
||||
(span
|
||||
(~tw :tokens "text-sm text-gray-500 ml-2")
|
||||
(get item :desc))))
|
||||
filtered)))))))
|
||||
|
||||
;; Tabs
|
||||
(defhandler
|
||||
ex-tab
|
||||
:path "/sx/(applications.(htmx.(api.tab)))"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key tab)
|
||||
(let
|
||||
((tab (or tab "overview")))
|
||||
(cond
|
||||
(= tab "overview")
|
||||
(div
|
||||
(~tw :tokens "p-4 space-y-2")
|
||||
(h3 (~tw :tokens "font-semibold text-stone-800") "Overview")
|
||||
(p
|
||||
(~tw :tokens "text-stone-600 text-sm")
|
||||
"htmx gives you access to AJAX, CSS Transitions, WebSockets and Server Sent Events directly in HTML, using attributes."))
|
||||
(= tab "features")
|
||||
(div
|
||||
(~tw :tokens "p-4 space-y-2")
|
||||
(h3 (~tw :tokens "font-semibold text-stone-800") "Features")
|
||||
(ul
|
||||
(~tw
|
||||
:tokens "list-disc list-inside text-sm text-stone-600 space-y-1")
|
||||
(li "Any element, any event")
|
||||
(li "Multiple swap strategies")
|
||||
(li "CSS transition support")
|
||||
(li "Out-of-band swaps")))
|
||||
(= tab "code")
|
||||
(div
|
||||
(~tw :tokens "p-4")
|
||||
(pre
|
||||
(~tw :tokens "text-sm bg-stone-100 rounded p-3")
|
||||
(code "(button :hx-get \"/api\" :hx-target \"#out\"\n \"Load\")")))
|
||||
true
|
||||
(div (~tw :tokens "p-4 text-stone-400") "Unknown tab"))))
|
||||
|
||||
;; Delete item — returns empty fragment to remove the element
|
||||
(defhandler
|
||||
ex-delete
|
||||
:path "/sx/(applications.(htmx.(api.delete)))"
|
||||
:method :delete
|
||||
:csrf false
|
||||
:returns "element"
|
||||
(&key)
|
||||
(<>))
|
||||
|
||||
;; Form submission
|
||||
(defhandler
|
||||
ex-form
|
||||
:path "/sx/(applications.(htmx.(api.form)))"
|
||||
:method :post
|
||||
:csrf false
|
||||
:returns "element"
|
||||
(&key name email)
|
||||
(div
|
||||
(~tw :tokens "p-4 bg-green-50 border border-green-200 rounded-lg")
|
||||
(p
|
||||
(~tw :tokens "text-green-800 font-medium")
|
||||
(str "Hello, " (or name "stranger") "!"))
|
||||
(p
|
||||
(~tw :tokens "text-sm text-green-600 mt-1")
|
||||
(str "Email: " (or email "not provided")))))
|
||||
|
||||
;; Slow endpoint for indicator demo
|
||||
(defhandler
|
||||
ex-slow
|
||||
:path "/sx/(applications.(htmx.(api.slow)))"
|
||||
:method :get
|
||||
:returns "element"
|
||||
(&key)
|
||||
(div
|
||||
(~tw :tokens "p-4 bg-amber-50 border border-amber-200 rounded-lg")
|
||||
(p (~tw :tokens "text-amber-800 font-medium") "Slow response received")
|
||||
(p
|
||||
(~tw :tokens "text-sm text-amber-600 mt-1")
|
||||
"This response was delayed")))
|
||||
|
||||
;; Append item (beforeend swap demo)
|
||||
(defhandler
|
||||
ex-append
|
||||
:path "/sx/(applications.(htmx.(api.append)))"
|
||||
:method :post
|
||||
:csrf false
|
||||
:returns "element"
|
||||
(&key)
|
||||
(div
|
||||
(~tw :tokens "p-2 border-b border-gray-100 text-sm text-stone-700")
|
||||
"New item appended"))
|
||||
@@ -1,7 +1,6 @@
|
||||
;; _hyperscript playground API handler
|
||||
|
||||
(defhandler
|
||||
hs-compile
|
||||
:path "/sx/(applications.(hyperscript.(api.compile)))"
|
||||
:method :post
|
||||
:csrf false
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
(defhandler
|
||||
spec-detail
|
||||
:path "/sx/api/spec-detail"
|
||||
:method :get
|
||||
:returns "element"
|
||||
|
||||
Reference in New Issue
Block a user