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>
84 lines
3.9 KiB
Plaintext
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"))))
|