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:
2026-04-15 11:29:01 +00:00
parent a93e5924df
commit 4f02f82f4e
377 changed files with 9517 additions and 8694 deletions

View File

@@ -0,0 +1,14 @@
(defcomp
(&key (title :as string) (attrs :as list))
(~docs/attr-table
:title title
:rows (<>
(map
(fn
(a)
(~docs/attr-row
:attr (get a "name")
:description (get a "desc")
:exists (get a "exists")
:href (get a "href")))
attrs))))

18
sx/sx/docs/attr-table.sx Normal file
View File

@@ -0,0 +1,18 @@
(defcomp
(&key (title :as string) rows)
(div
(~tw :tokens "space-y-3")
(h3 (~tw :tokens "text-xl font-semibold text-stone-700") title)
(div
(~tw :tokens "overflow-x-auto rounded border border-stone-200")
(table
(~tw :tokens "w-full text-left text-sm")
(thead
(tr
(~tw :tokens "border-b border-stone-200 bg-stone-100")
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Attribute")
(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 text-center w-20")
"In sx?")))
(tbody rows)))))

View File

@@ -0,0 +1,6 @@
(defcomp
()
(button
:onclick "localStorage.removeItem('sx-components-hash');localStorage.removeItem('sx-components-src');var e=Sx.getEnv();Object.keys(e).forEach(function(k){if(k.charAt(0)==='~')delete e[k]});var b=this;b.textContent='Cleared!';setTimeout(function(){b.textContent='Clear component cache'},2000)"
(~tw :tokens "text-xs text-stone-400 hover:text-stone-600 border border-stone-200 rounded px-2 py-1 transition-colors")
"Clear component cache"))

24
sx/sx/docs/headers-row.sx Normal file
View File

@@ -0,0 +1,24 @@
(defcomp
(&key
(name :as string)
(value :as string)
(description :as string)
(href :as string?))
(tr
(~tw :tokens "border-b border-stone-100")
(td
(~tw :tokens "px-3 py-2 font-mono text-sm whitespace-nowrap")
(if
href
(a
:href href
:sx-get href
:sx-target "#sx-content"
:sx-select "#sx-content"
:sx-swap "outerHTML"
:sx-push-url "true"
(~tw :tokens "text-violet-700 hover:text-violet-900 underline")
name)
(span (~tw :tokens "text-violet-700") name)))
(td (~tw :tokens "px-3 py-2 font-mono text-sm text-stone-500") value)
(td (~tw :tokens "px-3 py-2 text-stone-700 text-sm") description)))

View File

@@ -0,0 +1,14 @@
(defcomp
(&key (title :as string) (headers :as list))
(~docs/headers-table
:title title
:rows (<>
(map
(fn
(h)
(~docs/headers-row
:name (get h "name")
:value (get h "value")
:description (get h "desc")
:href (get h "href")))
headers))))

View File

@@ -0,0 +1,16 @@
(defcomp
(&key (title :as string) rows)
(div
(~tw :tokens "space-y-3")
(h3 (~tw :tokens "text-xl font-semibold text-stone-700") title)
(div
(~tw :tokens "overflow-x-auto rounded border border-stone-200")
(table
(~tw :tokens "w-full text-left text-sm")
(thead
(tr
(~tw :tokens "border-b border-stone-200 bg-stone-100")
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Header")
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Value")
(th (~tw :tokens "px-3 py-2 font-medium text-stone-600") "Description")))
(tbody rows)))))

1
sx/sx/docs/label.sx Normal file
View File

@@ -0,0 +1 @@
(defcomp () (span (~tw :tokens "font-mono") "(<sx>)"))

8
sx/sx/docs/oob-code.sx Normal file
View File

@@ -0,0 +1,8 @@
(defcomp
(&key (target-id :as string) (text :as string))
(div
:id target-id
:sx-swap-oob "innerHTML"
(div
(~tw :tokens "not-prose bg-stone-100 rounded p-4 mt-3")
(pre (~tw :tokens "text-sm whitespace-pre-wrap break-words") (code text)))))

View File

@@ -0,0 +1,9 @@
(defcomp
(&key (id :as string))
(div
:id id
(div
(~tw :tokens "bg-stone-100 rounded p-4 mt-3")
(p
(~tw :tokens "text-stone-400 italic text-sm")
"Trigger the demo to see the actual content."))))

View File

@@ -0,0 +1,10 @@
(defcomp
(&key (primitives :as dict))
(<>
(map
(fn
(cat)
(~docs/primitives-table
:category cat
:primitives (get primitives cat)))
(keys primitives))))

View File

@@ -0,0 +1,32 @@
(defcomp
(&key
(name :as string)
(syntax :as string)
(doc :as string)
(tail-position :as string)
(example :as string))
(div
(~tw :tokens "not-prose border border-stone-200 rounded-lg p-4 space-y-3")
(div
(~tw :tokens "flex items-baseline gap-3")
(code (~tw :tokens "text-lg font-bold text-violet-700") name)
(when
(not (= tail-position "none"))
(span
(~tw :tokens "text-xs px-2 py-0.5 rounded-full bg-green-100 text-green-700")
"TCO")))
(when
(not (= syntax ""))
(pre
(~tw :tokens "bg-stone-100 rounded px-3 py-2 text-sm font-mono text-stone-700 overflow-x-auto")
syntax))
(p (~tw :tokens "text-stone-600 text-sm whitespace-pre-line") doc)
(when
(not (= tail-position ""))
(p
(~tw :tokens "text-xs text-stone-500")
(span (~tw :tokens "font-semibold") "Tail position: ")
tail-position))
(when
(not (= example ""))
(~docs/code :src (highlight example "lisp")))))

View File

@@ -0,0 +1,19 @@
(defcomp
(&key (category :as string) (forms :as list))
(div
(~tw :tokens "space-y-4")
(h3
(~tw :tokens "text-xl font-semibold text-stone-800 border-b border-stone-200 pb-2")
category)
(div
(~tw :tokens "space-y-4")
(map
(fn
(f)
(~docs/special-form-card
:name (get f "name")
:syntax (get f "syntax")
:doc (get f "doc")
:tail-position (get f "tail-position")
:example (get f "example")))
forms))))

View File

@@ -0,0 +1,8 @@
(defcomp
(&key (forms :as dict))
(<>
(map
(fn
(cat)
(~docs/special-forms-category :category cat :forms (get forms cat)))
(keys forms))))

19
sx/sx/docs/two-col-row.sx Normal file
View File

@@ -0,0 +1,19 @@
(defcomp
(&key (name :as string) (description :as string) (href :as string?))
(tr
(~tw :tokens "border-b border-stone-100")
(td
(~tw :tokens "px-3 py-2 font-mono text-sm whitespace-nowrap")
(if
href
(a
:href href
:sx-get href
:sx-target "#sx-content"
:sx-select "#sx-content"
:sx-swap "outerHTML"
:sx-push-url "true"
(~tw :tokens "text-violet-700 hover:text-violet-900 underline")
name)
(span (~tw :tokens "text-violet-700") name)))
(td (~tw :tokens "px-3 py-2 text-stone-700 text-sm") description)))

View File

@@ -0,0 +1,21 @@
(defcomp
(&key
(title :as string?)
(intro :as string?)
(col1 :as string?)
(col2 :as string?)
(items :as list))
(~docs/two-col-table
:title title
:intro intro
:col1 col1
:col2 col2
:rows (<>
(map
(fn
(item)
(~docs/two-col-row
:name (get item "name")
:description (get item "desc")
:href (get item "href")))
items))))

View File

@@ -0,0 +1,25 @@
(defcomp
(&key
(title :as string?)
(intro :as string?)
(col1 :as string?)
(col2 :as string?)
rows)
(div
(~tw :tokens "space-y-3")
(when title (h3 (~tw :tokens "text-xl font-semibold text-stone-700") title))
(when intro (p (~tw :tokens "text-stone-600 mb-6") intro))
(div
(~tw :tokens "overflow-x-auto rounded border border-stone-200")
(table
(~tw :tokens "w-full text-left text-sm")
(thead
(tr
(~tw :tokens "border-b border-stone-200 bg-stone-100")
(th
(~tw :tokens "px-3 py-2 font-medium text-stone-600")
(or col1 "Name"))
(th
(~tw :tokens "px-3 py-2 font-medium text-stone-600")
(or col2 "Description"))))
(tbody rows)))))