Files
rose-ash/sx/content/pages.py
giles 002cc49f2c
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 3m26s
Add 21 new interactive examples to sx docs site (27 total)
Loading: lazy loading, infinite scroll, progress bar
Forms: active search, inline validation, value select, reset on submit
Records: edit row, bulk update
Swap/DOM: swap positions, select filter, tabs
Display: animations, dialogs, keyboard shortcuts
HTTP: PUT/PATCH, JSON encoding, vals & headers
Resilience: loading states, request abort (sync replace), retry

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 02:26:10 +00:00

239 lines
11 KiB
Python

"""Documentation content for the sx docs site.
All page content as Python data structures, consumed by sx_components.py
to build s-expression page trees.
"""
from __future__ import annotations
# ---------------------------------------------------------------------------
# Navigation
# ---------------------------------------------------------------------------
DOCS_NAV = [
("Introduction", "/docs/introduction"),
("Getting Started", "/docs/getting-started"),
("Components", "/docs/components"),
("Evaluator", "/docs/evaluator"),
("Primitives", "/docs/primitives"),
("CSS", "/docs/css"),
("Server Rendering", "/docs/server-rendering"),
]
REFERENCE_NAV = [
("Attributes", "/reference/"),
("Headers", "/reference/headers"),
("Events", "/reference/events"),
("JS API", "/reference/js-api"),
]
PROTOCOLS_NAV = [
("Wire Format", "/protocols/wire-format"),
("Fragments", "/protocols/fragments"),
("Resolver I/O", "/protocols/resolver-io"),
("Internal Services", "/protocols/internal-services"),
("ActivityPub", "/protocols/activitypub"),
("Future", "/protocols/future"),
]
EXAMPLES_NAV = [
("Click to Load", "/examples/click-to-load"),
("Form Submission", "/examples/form-submission"),
("Polling", "/examples/polling"),
("Delete Row", "/examples/delete-row"),
("Inline Edit", "/examples/inline-edit"),
("OOB Swaps", "/examples/oob-swaps"),
("Lazy Loading", "/examples/lazy-loading"),
("Infinite Scroll", "/examples/infinite-scroll"),
("Progress Bar", "/examples/progress-bar"),
("Active Search", "/examples/active-search"),
("Inline Validation", "/examples/inline-validation"),
("Value Select", "/examples/value-select"),
("Reset on Submit", "/examples/reset-on-submit"),
("Edit Row", "/examples/edit-row"),
("Bulk Update", "/examples/bulk-update"),
("Swap Positions", "/examples/swap-positions"),
("Select Filter", "/examples/select-filter"),
("Tabs", "/examples/tabs"),
("Animations", "/examples/animations"),
("Dialogs", "/examples/dialogs"),
("Keyboard Shortcuts", "/examples/keyboard-shortcuts"),
("PUT / PATCH", "/examples/put-patch"),
("JSON Encoding", "/examples/json-encoding"),
("Vals & Headers", "/examples/vals-and-headers"),
("Loading States", "/examples/loading-states"),
("Request Abort", "/examples/sync-replace"),
("Retry", "/examples/retry"),
]
ESSAYS_NAV = [
("sx sucks", "/essays/sx-sucks"),
("Why S-Expressions", "/essays/why-sexps"),
("The htmx/React Hybrid", "/essays/htmx-react-hybrid"),
("On-Demand CSS", "/essays/on-demand-css"),
]
MAIN_NAV = [
("Docs", "/docs/introduction"),
("Reference", "/reference/"),
("Protocols", "/protocols/wire-format"),
("Examples", "/examples/click-to-load"),
("Essays", "/essays/sx-sucks"),
]
# ---------------------------------------------------------------------------
# Reference: Attributes
# ---------------------------------------------------------------------------
REQUEST_ATTRS = [
("sx-get", "Issue a GET request to the given URL", True),
("sx-post", "Issue a POST request to the given URL", True),
("sx-put", "Issue a PUT request to the given URL", True),
("sx-delete", "Issue a DELETE request to the given URL", True),
("sx-patch", "Issue a PATCH request to the given URL", True),
]
BEHAVIOR_ATTRS = [
("sx-trigger", "Specifies the event that triggers the request. Modifiers: once, changed, delay:<time>, from:<selector>, intersect, revealed, load, every:<time>", True),
("sx-target", "CSS selector for the target element to update", True),
("sx-swap", "How to swap the response: outerHTML, innerHTML, afterend, beforeend, afterbegin, beforebegin, delete, none", True),
("sx-swap-oob", "Out-of-band swap — update elements elsewhere in the DOM by ID", True),
("sx-select", "CSS selector to pick a fragment from the response", True),
("sx-confirm", "Shows a confirmation dialog before issuing the request", True),
("sx-push-url", "Push the request URL into the browser location bar", True),
("sx-sync", "Synchronization strategy for requests from this element", True),
("sx-encoding", "Set the encoding for the request (e.g. multipart/form-data)", True),
("sx-headers", "Add headers to the request as a JSON string", True),
("sx-include", "Include additional element values in the request", True),
("sx-vals", "Add values to the request as a JSON string", True),
("sx-media", "Only enable this element when the media query matches", True),
("sx-disable", "Disable sx processing on this element and its children", True),
]
SX_UNIQUE_ATTRS = [
("sx-retry", "Exponential backoff retry on request failure", True),
("data-sx", "Client-side rendering — evaluate the sx source in this attribute and render into the element", True),
("data-sx-env", "Provide environment variables as JSON for data-sx rendering", True),
]
HTMX_MISSING_ATTRS = [
("hx-boost", "Progressively enhance links and forms (not yet implemented)", False),
("hx-preload", "Preload content on hover/focus (not yet implemented)", False),
("hx-preserve", "Preserve element across swaps (not yet implemented)", False),
("hx-optimistic", "Optimistic UI updates (not yet implemented)", False),
("hx-indicator", "sx uses .sx-request CSS class instead — no dedicated attribute (not yet implemented)", False),
("hx-validate", "Custom validation (not yet implemented — sx has sx-disable)", False),
("hx-ignore", "Ignore element (not yet implemented — sx has sx-disable)", False),
]
# ---------------------------------------------------------------------------
# Reference: Headers
# ---------------------------------------------------------------------------
REQUEST_HEADERS = [
("SX-Request", "true", "Set on every sx-initiated request"),
("SX-Current-URL", "URL", "The current URL of the browser"),
("SX-Target", "CSS selector", "The target element for the response"),
("SX-Components", "~comp1,~comp2,...", "Component names the client already has cached"),
("SX-Css", "hash or class list", "CSS classes/hash the client already has"),
("SX-History-Restore", "true", "Set when restoring from browser history"),
("SX-Css-Hash", "8-char hash", "Hash of the client's known CSS class set"),
]
RESPONSE_HEADERS = [
("SX-Css-Hash", "8-char hash", "Hash of the cumulative CSS class set after this response"),
("SX-Css-Add", "class1,class2,...", "New CSS classes added by this response"),
]
# ---------------------------------------------------------------------------
# Reference: Events
# ---------------------------------------------------------------------------
EVENTS = [
("sx:beforeRequest", "Fired before an sx request is issued. Call preventDefault() to cancel."),
("sx:afterRequest", "Fired after a successful sx response is received."),
("sx:afterSwap", "Fired after the response has been swapped into the DOM."),
("sx:afterSettle", "Fired after the DOM has settled (scripts executed, etc)."),
("sx:responseError", "Fired on HTTP error responses (4xx, 5xx)."),
("sx:sendError", "Fired when the request fails to send (network error)."),
]
# ---------------------------------------------------------------------------
# Reference: JS API
# ---------------------------------------------------------------------------
JS_API = [
("Sx.parse(text)", "Parse a single s-expression from text"),
("Sx.parseAll(text)", "Parse multiple s-expressions from text"),
("Sx.eval(expr, env)", "Evaluate an expression in the given environment"),
("Sx.render(expr, env)", "Render an expression to DOM nodes"),
("Sx.renderToString(expr, env)", "Render an expression to an HTML string"),
("Sx.renderComponent(name, kwargs, env)", "Render a named component with keyword arguments"),
("Sx.loadComponents(text)", "Parse and register component definitions"),
("Sx.getEnv()", "Get the current component environment"),
("Sx.mount(target, expr, env)", "Mount an expression into a DOM element"),
("Sx.update(target, newEnv)", "Re-render an element with new environment data"),
("Sx.hydrate(root)", "Find and render all [data-sx] elements within root"),
("SxEngine.process(root)", "Process all sx attributes in the DOM subtree"),
("SxEngine.executeRequest(elt, verb, url)", "Programmatically trigger an sx request"),
]
# ---------------------------------------------------------------------------
# Primitives
# ---------------------------------------------------------------------------
PRIMITIVES = {
"Arithmetic": ["+", "-", "*", "/", "mod", "sqrt", "pow", "abs", "floor", "ceil", "round", "min", "max"],
"Comparison": ["=", "!=", "<", ">", "<=", ">="],
"Logic": ["not", "and", "or"],
"String": ["str", "upper", "lower", "trim", "split", "join", "starts-with?", "ends-with?", "replace", "substring"],
"Collections": ["list", "dict", "len", "first", "last", "rest", "nth", "cons", "append", "keys", "vals", "merge", "assoc", "range", "concat", "reverse", "sort", "flatten", "zip"],
"Higher-Order": ["map", "map-indexed", "filter", "reduce", "some", "every?", "for-each"],
"Predicates": ["nil?", "number?", "string?", "list?", "dict?", "empty?", "contains?", "odd?", "even?", "zero?"],
"Type Conversion": ["int", "float", "number"],
}
# ---------------------------------------------------------------------------
# Example items for delete demo
# ---------------------------------------------------------------------------
DELETE_DEMO_ITEMS = [
("1", "Implement dark mode"),
("2", "Fix login bug"),
("3", "Write documentation"),
("4", "Deploy to production"),
("5", "Add unit tests"),
]
# ---------------------------------------------------------------------------
# Static data for new examples
# ---------------------------------------------------------------------------
SEARCH_LANGUAGES = [
"Python", "JavaScript", "TypeScript", "Rust", "Go", "Java", "C", "C++",
"Ruby", "Elixir", "Haskell", "Clojure", "Scala", "Kotlin", "Swift",
"Zig", "OCaml", "Lua", "Perl", "PHP",
]
PROFILE_DEFAULT = {"name": "Ada Lovelace", "email": "ada@example.com", "role": "Engineer"}
BULK_USERS = [
{"id": "1", "name": "Alice Chen", "email": "alice@example.com", "status": "active"},
{"id": "2", "name": "Bob Rivera", "email": "bob@example.com", "status": "inactive"},
{"id": "3", "name": "Carol Zhang", "email": "carol@example.com", "status": "active"},
{"id": "4", "name": "Dan Okafor", "email": "dan@example.com", "status": "inactive"},
{"id": "5", "name": "Eve Larsson", "email": "eve@example.com", "status": "active"},
]
VALUE_SELECT_DATA = {
"Languages": ["Python", "JavaScript", "Rust", "Go"],
"Frameworks": ["Quart", "FastAPI", "React", "Svelte"],
"Databases": ["PostgreSQL", "Redis", "SQLite", "MongoDB"],
}
EDIT_ROW_DATA = [
{"id": "1", "name": "Widget A", "price": "19.99", "stock": "142"},
{"id": "2", "name": "Widget B", "price": "24.50", "stock": "89"},
{"id": "3", "name": "Widget C", "price": "12.00", "stock": "305"},
{"id": "4", "name": "Widget D", "price": "45.00", "stock": "67"},
]