"""All content generator functions and dispatchers for sx docs pages.""" from __future__ import annotations from .renders import _code, _example_code, _placeholder, _oob_code, _clear_components_btn from .utils import _attr_table_sx, _primitives_section_sx, _headers_table_sx # --------------------------------------------------------------------------- # Dispatcher functions — route slugs to content builders # --------------------------------------------------------------------------- async def _docs_content_sx(slug: str) -> str: """Route to the right docs content builder.""" import inspect builders = { "introduction": _docs_introduction_sx, "getting-started": _docs_getting_started_sx, "components": _docs_components_sx, "evaluator": _docs_evaluator_sx, "primitives": _docs_primitives_sx, "css": _docs_css_sx, "server-rendering": _docs_server_rendering_sx, } builder = builders.get(slug, _docs_introduction_sx) result = builder() return await result if inspect.isawaitable(result) else result async def _reference_content_sx(slug: str) -> str: import inspect builders = { "attributes": _reference_attrs_sx, "headers": _reference_headers_sx, "events": _reference_events_sx, "js-api": _reference_js_api_sx, } result = builders.get(slug or "", _reference_attrs_sx)() return await result if inspect.isawaitable(result) else result def _protocol_content_sx(slug: str) -> str: builders = { "wire-format": _protocol_wire_format_sx, "fragments": _protocol_fragments_sx, "resolver-io": _protocol_resolver_io_sx, "internal-services": _protocol_internal_services_sx, "activitypub": _protocol_activitypub_sx, "future": _protocol_future_sx, } return builders.get(slug, _protocol_wire_format_sx)() def _examples_content_sx(slug: str) -> str: builders = { "click-to-load": _example_click_to_load_sx, "form-submission": _example_form_submission_sx, "polling": _example_polling_sx, "delete-row": _example_delete_row_sx, "inline-edit": _example_inline_edit_sx, "oob-swaps": _example_oob_swaps_sx, "lazy-loading": _example_lazy_loading_sx, "infinite-scroll": _example_infinite_scroll_sx, "progress-bar": _example_progress_bar_sx, "active-search": _example_active_search_sx, "inline-validation": _example_inline_validation_sx, "value-select": _example_value_select_sx, "reset-on-submit": _example_reset_on_submit_sx, "edit-row": _example_edit_row_sx, "bulk-update": _example_bulk_update_sx, "swap-positions": _example_swap_positions_sx, "select-filter": _example_select_filter_sx, "tabs": _example_tabs_sx, "animations": _example_animations_sx, "dialogs": _example_dialogs_sx, "keyboard-shortcuts": _example_keyboard_shortcuts_sx, "put-patch": _example_put_patch_sx, "json-encoding": _example_json_encoding_sx, "vals-and-headers": _example_vals_and_headers_sx, "loading-states": _example_loading_states_sx, "sync-replace": _example_sync_replace_sx, "retry": _example_retry_sx, } return builders.get(slug, _example_click_to_load_sx)() def _essay_content_sx(slug: str) -> str: builders = { "sx-sucks": _essay_sx_sucks, "why-sexps": _essay_why_sexps, "htmx-react-hybrid": _essay_htmx_react_hybrid, "on-demand-css": _essay_on_demand_css, "client-reactivity": _essay_client_reactivity, "sx-native": _essay_sx_native, "sx-manifesto": _essay_sx_manifesto, "tail-call-optimization": _essay_tail_call_optimization, "continuations": _essay_continuations, } return builders.get(slug, _essay_sx_sucks)() # --------------------------------------------------------------------------- # Individual content builders # --------------------------------------------------------------------------- def _docs_introduction_sx() -> str: return ( '(~doc-page :title "Introduction"' ' (~doc-section :title "What is sx?" :id "what"' ' (p :class "text-stone-600"' ' "sx is an s-expression language for building web UIs. ' 'It combines htmx\'s server-first hypermedia approach with React\'s component model. ' 'The server sends s-expression source code over the wire. The client parses, evaluates, and renders it to DOM.")' ' (p :class "text-stone-600"' ' "The same evaluator runs on both server (Python) and client (JavaScript). ' 'Components defined once render identically in both environments."))' ' (~doc-section :title "Design decisions" :id "design"' ' (p :class "text-stone-600"' ' "HTML elements are first-class: (div :class \\"card\\" (p \\"hello\\")) renders exactly what you\'d expect. ' 'Components use defcomp with keyword parameters and optional children. ' 'The evaluator supports let bindings, conditionals, lambda, map/filter/reduce, and ~80 primitives.")' ' (p :class "text-stone-600"' ' "sx replaces the pattern of ' 'shipping a JS framework + build step + client-side router + state management library ' 'just to render some server data. For most applications, sx eliminates the need for ' 'JavaScript entirely — htmx attributes handle interactivity, hyperscript handles small behaviours, ' 'and the server handles everything else."))' ' (~doc-section :title "What sx is not" :id "not"' ' (ul :class "space-y-2 text-stone-600"' ' (li "Not a general-purpose programming language — it\'s a UI rendering language")' ' (li "Not a full Lisp — it has macros and TCO, but no continuations or call/cc")' ' (li "Not production-hardened at scale — it runs one website"))))' ) def _docs_getting_started_sx() -> str: c1 = _code('(div :class "p-4 bg-white rounded"\n (h1 :class "text-2xl font-bold" "Hello, world!")\n (p "This is rendered from an s-expression."))') c2 = _code('(button\n :sx-get "/api/data"\n :sx-target "#result"\n :sx-swap "innerHTML"\n "Load data")') return ( f'(~doc-page :title "Getting Started"' f' (~doc-section :title "Minimal example" :id "minimal"' f' (p :class "text-stone-600"' f' "An sx response is s-expression source code with content type text/sx:")' f' {c1}' f' (p :class "text-stone-600"' f' "Add sx-get to any element to make it fetch and render sx:"))' f' (~doc-section :title "Hypermedia attributes" :id "attrs"' f' (p :class "text-stone-600"' f' "Like htmx, sx adds attributes to HTML elements to trigger HTTP requests:")' f' {c2}' f' (p :class "text-stone-600"' f' "sx-get, sx-post, sx-put, sx-delete, sx-patch — all work the same way. ' f'The response is parsed as sx and rendered into the target element.")))' ) def _docs_components_sx() -> str: c1 = _code('(defcomp ~card (&key title subtitle &rest children)\n' ' (div :class "border rounded p-4"\n' ' (h2 :class "font-bold" title)\n' ' (when subtitle (p :class "text-stone-500" subtitle))\n' ' (div :class "mt-3" children)))') c2 = _code('(~card :title "My Card" :subtitle "A description"\n' ' (p "First child")\n' ' (p "Second child"))') return ( f'(~doc-page :title "Components"' f' (~doc-section :title "defcomp" :id "defcomp"' f' (p :class "text-stone-600"' f' "Components are defined with defcomp. They take keyword parameters and optional children:")' f' {c1}' f' (p :class "text-stone-600"' f' "Use components with the ~ prefix:")' f' {c2})' f' (~doc-section :title "Component caching" :id "caching"' f' (p :class "text-stone-600"' f' "Component definitions are sent in a