Files
rose-ash/sx/sx/applications/hyperscript/index.sx
giles 4f02f82f4e 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>
2026-04-15 11:29:01 +00:00

84 lines
3.9 KiB
Plaintext

;; ── Live demo: actual hyperscript running ───────────────────────
(defcomp
()
(~docs/page
:title "_hyperscript Playground"
(p
:class "text-lg text-gray-600 mb-6"
"Compile "
(code "_hyperscript")
" to SX expressions. "
"The same "
(code "_=\"...\"")
" syntax, compiled to cached bytecode instead of re-parsed every page load.")
(~docs/section
:title "Interactive Playground"
:id "playground"
(p
"Edit the hyperscript source and click Compile to see the tokenized, parsed, and compiled SX output.")
(~hyperscript/playground))
(~docs/section
:title "Live Demo"
:id "live-demo"
(p
"These buttons have "
(code "_=\"...\"")
" attributes — hyperscript compiled to SX and activated at boot.")
(~hyperscript/live-demo))
(~docs/section
:title "Pipeline"
:id "pipeline"
(p "Every hyperscript string passes through three stages:")
(ol
:class "list-decimal list-inside space-y-1 text-sm text-gray-700 mb-4"
(li
(strong "Tokenize")
" — source string to typed token stream (keywords, classes, ids, operators, strings)")
(li
(strong "Parse")
" — token stream to AST (commands, expressions, features)")
(li
(strong "Compile")
" — AST to SX expressions targeting "
(code "web/lib/dom.sx")
" primitives"))
(p
"The compiled SX is wrapped in "
(code "(fn (me) ...)")
" and evaluated with "
(code "me")
" bound to the element. Hyperscript variables are visible to "
(code "eval (sx-expr)")
" escapes."))
(~docs/section
:title "Examples"
:id "examples"
(style
"\n button.active { background-color: #7c3aed !important; color: white !important; border-color: #7c3aed !important; }\n button.active:hover { background-color: #6d28d9 !important; }\n button.light { background-color: #fef3c7 !important; color: #92400e !important; border-color: #f59e0b !important; }\n button.light:hover { background-color: #fde68a !important; }\n button.dark { background-color: #1e293b !important; color: #e2e8f0 !important; border-color: #475569 !important; }\n button.dark:hover { background-color: #334155 !important; }\n .animate-bounce { animation: bounce 1s; }\n @keyframes bounce {\n 0%, 100% { transform: translateY(0); }\n 50% { transform: translateY(-25%); }\n }")
(~hyperscript/example
:source "on click add .active to me"
:description "Event handler: click adds a CSS class")
(~hyperscript/example
:source "on click toggle between .light and .dark on me"
:description "Toggle between two states")
(~hyperscript/example
:source "on click set my innerHTML to eval (str \"Hello from \" (+ 2 3) \" worlds\")"
:description "SX escape: evaluate SX expressions from hyperscript")
(~hyperscript/example
:source "on click put \"<b>Rendered!</b>\" into #target"
:description "Target another element by CSS selector")
(div
:id "target"
(~tw
:tokens "border border-dashed border-gray-300 rounded-lg p-3 min-h-[2rem] text-sm text-gray-400")
"← render target")
(~hyperscript/example
:source "def double(n) return n + n end"
:description "Define reusable functions")
(~hyperscript/example
:source "on click repeat 3 times add .active to me then wait 300ms then remove .active from me then wait 300ms end"
:description "Iteration: repeat with timed animation (continuation after loop pending)")
(~hyperscript/example
:source "behavior Draggable on mousedown add .dragging to me end on mouseup remove .dragging from me end end"
:description "Reusable behaviors — install on any element"))))