Compare commits
3 Commits
2211655060
...
48d493e9cc
| Author | SHA1 | Date | |
|---|---|---|---|
| 48d493e9cc | |||
| 7556cc303d | |||
| 919998be1c |
27
sx/app.py
27
sx/app.py
@@ -69,30 +69,17 @@ def create_app() -> "Quart":
|
||||
|
||||
# Minimal shell — no Prism, no SweetAlert, no body.js
|
||||
# sx docs uses custom highlight.py, not Prism; body.js is for legacy apps
|
||||
# Load init SX from file — styles + nav behavior, no inline Python strings
|
||||
import os as _os
|
||||
_init_path = _os.path.join(_os.path.dirname(__file__), "sxc", "init-client.sx.txt")
|
||||
with open(_init_path) as _f:
|
||||
_init_sx = _f.read()
|
||||
app.config["SX_SHELL"] = {
|
||||
"head_scripts": [], # no CDN scripts
|
||||
"body_scripts": [], # no body.js
|
||||
"inline_head_js": "", # no pre-boot JS (hover-capable, close-details unused)
|
||||
"inline_css": (
|
||||
".sx-indicator{display:none}"
|
||||
".sx-request .sx-indicator{display:inline-flex}"
|
||||
"@keyframes sxJiggle{0%,100%{transform:translateX(0)}"
|
||||
"25%{transform:translateX(-.5px)}75%{transform:translateX(.5px)}}"
|
||||
"a.sx-request{animation:sxJiggle .3s ease-in-out infinite}"
|
||||
),
|
||||
# Nav link aria-selected update on client-side routing — pure SX
|
||||
"init_sx": (
|
||||
'(dom-listen (dom-body) "sx:clientRoute"'
|
||||
' (fn (e)'
|
||||
' (let ((p (get (event-detail e) "pathname")))'
|
||||
' (when p'
|
||||
' (for-each'
|
||||
' (fn (a) (dom-set-attr a "aria-selected" "false"))'
|
||||
' (dom-query-all "nav a[aria-selected]"))'
|
||||
' (for-each'
|
||||
' (fn (a) (dom-set-attr a "aria-selected" "true"))'
|
||||
' (dom-query-all (str "nav a[href=\\"" p "\\"]")))))))'
|
||||
),
|
||||
"inline_css": "", # styles injected via CSSX from init.sx
|
||||
"init_sx": _init_sx,
|
||||
}
|
||||
|
||||
app.url_map.strict_slashes = False
|
||||
|
||||
@@ -133,7 +133,9 @@
|
||||
{:label "Boot" :href "/sx/(language.(spec.boot))"}
|
||||
{:label "Router" :href "/sx/(language.(spec.router))"})}
|
||||
{:label "Reactive" :href "/sx/(language.(spec.reactive))" :children (list
|
||||
{:label "Signals" :href "/sx/(language.(spec.signals))"})}
|
||||
{:label "Signals" :href "/sx/(language.(spec.signals))"}
|
||||
{:label "CEK Frames" :href "/sx/(language.(spec.frames))"}
|
||||
{:label "CEK Machine" :href "/sx/(language.(spec.cek))"})}
|
||||
{:label "Host Interface" :href "/sx/(language.(spec.host))" :children (list
|
||||
{:label "Boundary" :href "/sx/(language.(spec.boundary))"}
|
||||
{:label "Forms" :href "/sx/(language.(spec.forms))"}
|
||||
@@ -315,7 +317,13 @@
|
||||
(define reactive-spec-items (list
|
||||
(dict :slug "signals" :filename "signals.sx" :title "Signals"
|
||||
:desc "Fine-grained reactive primitives — signal, computed, effect, batch."
|
||||
:prose "The signals module defines a fine-grained reactive system for client-side islands. Signals are containers for values that notify subscribers on change. Computed signals derive values lazily from other signals. Effects run side-effects when their dependencies change, with automatic cleanup. Batch coalesces multiple signal writes into a single notification pass. Island scope management ensures all signals, computeds, and effects are cleaned up when an island is removed from the DOM. The spec defines the reactive graph topology and update algorithm — each platform implements the actual signal/tracking types natively.")))
|
||||
:prose "The signals module defines a fine-grained reactive system for client-side islands. Signals are containers for values that notify subscribers on change. Computed signals derive values lazily from other signals. Effects run side-effects when their dependencies change, with automatic cleanup. Batch coalesces multiple signal writes into a single notification pass. Island scope management ensures all signals, computeds, and effects are cleaned up when an island is removed from the DOM. The spec defines the reactive graph topology and update algorithm — each platform implements the actual signal/tracking types natively.")
|
||||
(dict :slug "frames" :filename "frames.sx" :title "CEK Frames"
|
||||
:desc "Continuation frame types for the explicit CEK machine."
|
||||
:prose "Frames define what to do next when a sub-evaluation completes. Each frame type is a dict with a type key and frame-specific data. IfFrame, WhenFrame, BeginFrame handle control flow. LetFrame, DefineFrame, SetFrame handle bindings. ArgFrame tracks function call argument evaluation. MapFrame, FilterFrame, ReduceFrame, ForEachFrame drive higher-order forms element by element through the CEK machine. ReactiveResetFrame and DerefFrame enable deref-as-shift — the core reactive mechanism where deref inside a reactive boundary captures the continuation as a signal subscriber.")
|
||||
(dict :slug "cek" :filename "cek.sx" :title "CEK Machine"
|
||||
:desc "Explicit CEK machine evaluator — step function, run loop, reactive shift."
|
||||
:prose "The CEK machine makes evaluation explicit. Every step is a pure function from state to state: Control (expression), Environment (bindings), Kontinuation (stack of frames). step-eval dispatches on expression type — literals pass through, symbols are looked up, lists dispatch on head (special forms, higher-order forms, macros, function calls). step-continue dispatches on the top frame type. Higher-order forms (map, filter, reduce, for-each, some, every?) step element by element, so deref-as-shift works inside callbacks. cek-call replaces invoke as the universal function dispatch — lambdas go through cek-run, native callables through apply.")))
|
||||
|
||||
(define host-spec-items (list
|
||||
(dict :slug "boundary" :filename "boundary.sx" :title "Boundary"
|
||||
@@ -400,6 +408,7 @@
|
||||
:children (list
|
||||
{:label "Docs" :href "/sx/(language.(doc))" :children docs-nav-items}
|
||||
{:label "Specs" :href "/sx/(language.(spec))" :children specs-nav-items}
|
||||
{:label "Spec Explorer" :href "/sx/(language.(spec.(explore.evaluator)))"}
|
||||
{:label "Bootstrappers" :href "/sx/(language.(bootstrapper))" :children bootstrappers-nav-items}
|
||||
{:label "Testing" :href "/sx/(language.(test))" :children testing-nav-items})}
|
||||
{:label "Applications" :href "/sx/(applications)"
|
||||
|
||||
24
sx/sxc/init-client.sx.txt
Normal file
24
sx/sxc/init-client.sx.txt
Normal file
@@ -0,0 +1,24 @@
|
||||
;; ---------------------------------------------------------------------------
|
||||
;; SX app boot — styles and behaviors injected on page load
|
||||
;;
|
||||
;; Replaces inline_css and init_sx from Python app config.
|
||||
;; Called as a data-init script on every page.
|
||||
;; ---------------------------------------------------------------------------
|
||||
|
||||
;; Framework styles — request indicators + link jiggle
|
||||
(collect! "cssx" ".sx-indicator{display:none}")
|
||||
(collect! "cssx" ".sx-request .sx-indicator{display:inline-flex}")
|
||||
(collect! "cssx" "@keyframes sxJiggle{0%,100%{transform:translateX(0)}25%{transform:translateX(-.5px)}75%{transform:translateX(.5px)}}")
|
||||
(collect! "cssx" "a.sx-request{animation:sxJiggle .3s ease-in-out infinite}")
|
||||
|
||||
;; Nav link aria-selected update on client-side routing
|
||||
(dom-listen (dom-body) "sx:clientRoute"
|
||||
(fn (e)
|
||||
(let ((p (get (event-detail e) "pathname")))
|
||||
(when p
|
||||
(for-each
|
||||
(fn (a) (dom-set-attr a "aria-selected" "false"))
|
||||
(dom-query-all "nav a[aria-selected]"))
|
||||
(for-each
|
||||
(fn (a) (dom-set-attr a "aria-selected" "true"))
|
||||
(dom-query-all (str "nav a[href=\"" p "\"]")))))))
|
||||
Reference in New Issue
Block a user