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>
57 lines
3.0 KiB
Plaintext
57 lines
3.0 KiB
Plaintext
(defcomp
|
|
(&key (spec-title :as string) (spec-files :as list))
|
|
(~docs/page
|
|
:title (or spec-title "Specs")
|
|
(p
|
|
(~tw :tokens "text-stone-600 mb-6")
|
|
(case
|
|
spec-title
|
|
"Core Language"
|
|
"The core specification defines the language itself — parsing, evaluation, primitives, special forms, and shared rendering definitions. These five files are platform-independent and sufficient to implement SX on any target."
|
|
"Adapters"
|
|
"Adapters connect the core language to specific environments. Each adapter takes evaluated expression trees and produces output for its target — DOM nodes, HTML strings, SX wire format, or async-aware server rendering."
|
|
"Browser Runtime"
|
|
"The browser runtime handles the client-side lifecycle: parsing triggers, making requests, swapping content, managing history, and booting the page. Split into pure logic (engine), browser wiring (orchestration), startup (boot), and URL matching (router)."
|
|
"Reactive System"
|
|
"Fine-grained reactive primitives for client-side islands. Signals, computed values, effects, and batching — the reactive graph that powers L2-L3 interactivity without a virtual DOM."
|
|
"Host Interface"
|
|
"The contract between SX and its host environment. Boundary declarations specify what the host must provide, forms define server-side application constructs, and page helpers offer pure data transformations."
|
|
"Extensions"
|
|
"Optional bolt-on specifications that extend the core language. Bootstrappers include them only when the target requests them. Code that doesn't use extensions pays zero cost."
|
|
:else ""))
|
|
(div
|
|
(~tw :tokens "space-y-8")
|
|
(map
|
|
(fn
|
|
(spec)
|
|
(div
|
|
(~tw :tokens "space-y-3")
|
|
(div
|
|
(~tw :tokens "flex items-baseline gap-3")
|
|
(h2
|
|
(~tw :tokens "text-2xl font-semibold text-stone-800")
|
|
(a
|
|
:href (get spec "href")
|
|
:sx-get (get spec "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")
|
|
(get spec "title")))
|
|
(span
|
|
(~tw :tokens "text-sm text-stone-400 font-mono")
|
|
(get spec "filename")))
|
|
(p (~tw :tokens "text-stone-600") (get spec "desc"))
|
|
(when
|
|
(get spec "prose")
|
|
(p
|
|
(~tw :tokens "text-sm text-stone-500 leading-relaxed")
|
|
(get spec "prose")))
|
|
(div
|
|
(~tw :tokens "not-prose bg-stone-100 rounded-lg p-5 max-h-72 overflow-y-auto")
|
|
(pre
|
|
(~tw :tokens "text-xs leading-relaxed whitespace-pre-wrap break-words")
|
|
(code (highlight (get spec "source") "sx"))))))
|
|
spec-files))))
|