Added (~cssx/flush) to shell after sx-root div — picks up CSS rules generated during island SSR via (collect! "cssx" ...). Registered clear-collected! primitive for the flush component. Standard CSSX classes now styled server-side. Custom colour shades (e.g. text-violet-699) still need investigation. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
89 lines
5.2 KiB
Plaintext
89 lines
5.2 KiB
Plaintext
;; ---------------------------------------------------------------------------
|
|
;; Page shell — the outermost HTML document structure
|
|
;;
|
|
;; Replaces the Python HTML string template. All page data is computed in
|
|
;; Python and passed as keyword arguments. The component just arranges
|
|
;; the precomputed values into HTML structure.
|
|
;;
|
|
;; raw! is used for:
|
|
;; - <!doctype html> (not an element)
|
|
;; - Script/style content (must not be HTML-escaped)
|
|
;; - Pre-rendered meta HTML from callers
|
|
;; ---------------------------------------------------------------------------
|
|
|
|
(defcomp ~shared:shell/sx-page-shell (&key (title :as string) (meta-html :as string?) (csrf :as string)
|
|
(sx-css :as string?) (sx-css-classes :as string?)
|
|
(component-hash :as string?) (component-defs :as string?)
|
|
(pages-sx :as string?) (page-sx :as string?)
|
|
(body-html :as string?)
|
|
(asset-url :as string) (sx-js-hash :as string) (body-js-hash :as string?)
|
|
(head-scripts :as list?) (inline-css :as string?) (inline-head-js :as string?)
|
|
(init-sx :as string?) (body-scripts :as list?))
|
|
(<>
|
|
(raw! "<!doctype html>")
|
|
(html :lang "en"
|
|
(head
|
|
(meta :charset "utf-8")
|
|
(meta :name "viewport" :content "width=device-width, initial-scale=1")
|
|
(meta :name "robots" :content "index,follow")
|
|
(meta :name "theme-color" :content "#ffffff")
|
|
(title title)
|
|
(when meta-html (raw! meta-html))
|
|
(meta :name "csrf-token" :content csrf)
|
|
(style :id "sx-css" (raw! (or sx-css "")))
|
|
(meta :name "sx-css-classes" :content (or sx-css-classes ""))
|
|
;; CDN / head scripts — configurable per app
|
|
;; Pass a list (even empty) to override defaults; nil = use defaults
|
|
(if (not (nil? head-scripts))
|
|
(map (fn (src) (script :src src)) head-scripts)
|
|
;; Default: Prism + SweetAlert (legacy apps)
|
|
(<>
|
|
(script :src "https://unpkg.com/prismjs/prism.js")
|
|
(script :src "https://unpkg.com/prismjs/components/prism-javascript.min.js")
|
|
(script :src "https://unpkg.com/prismjs/components/prism-python.min.js")
|
|
(script :src "https://unpkg.com/prismjs/components/prism-bash.min.js")
|
|
(script :src "https://cdn.jsdelivr.net/npm/sweetalert2@11")))
|
|
;; Inline JS — skipped when app provides its own inline-head-js (even empty)
|
|
(if (not (nil? inline-head-js))
|
|
(when (not (empty? inline-head-js)) (script (raw! inline-head-js)))
|
|
(<>
|
|
(script (raw! "if(matchMedia('(hover:hover) and (pointer:fine)').matches){document.documentElement.classList.add('hover-capable')}"))
|
|
(script (raw! "document.addEventListener('click',function(e){var t=e.target.closest('[data-close-details]');if(!t)return;var d=t.closest('details');if(d)d.removeAttribute('open')})"))))
|
|
;; Inline CSS — configurable per app
|
|
;; Pass a string (even empty) to override defaults; nil = use defaults
|
|
(if (not (nil? inline-css))
|
|
(style (raw! inline-css))
|
|
;; Default: all shared styles (legacy apps)
|
|
(style (raw! "details[data-toggle-group=\"mobile-panels\"]>summary{list-style:none}
|
|
details[data-toggle-group=\"mobile-panels\"]>summary::-webkit-details-marker{display:none}
|
|
@media(min-width:768px){.nav-group:focus-within .submenu,.nav-group:hover .submenu{display:block}}
|
|
img{max-width:100%;height:auto}
|
|
.clamp-2{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}
|
|
.clamp-3{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
|
|
.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}
|
|
details.group{overflow:hidden}details.group>summary{list-style:none}details.group>summary::-webkit-details-marker{display:none}
|
|
.sx-indicator{display:none}.sx-request .sx-indicator{display:inline-flex}
|
|
.sx-error .sx-indicator{display:none}.sx-loading .sx-indicator{display:inline-flex}
|
|
.js-wrap.open .js-pop{display:block}.js-wrap.open .js-backdrop{display:block}"))))
|
|
(body :class "bg-stone-50 text-stone-900"
|
|
;; Server-rendered HTML — visible immediately before JS loads
|
|
(div :id "sx-root" (raw! (or body-html "")))
|
|
;; Flush CSSX rules collected during island SSR
|
|
(~cssx/flush)
|
|
(script :type "text/sx" :data-components true :data-hash component-hash
|
|
(raw! (or component-defs "")))
|
|
(when init-sx
|
|
(script :type "text/sx" :data-init true
|
|
(raw! init-sx)))
|
|
(script :type "text/sx-pages"
|
|
(raw! (or pages-sx "")))
|
|
(script :type "text/sx" :data-mount "#sx-root"
|
|
(raw! (or page-sx "")))
|
|
(script :src (str asset-url "/scripts/sx-browser.js?v=" sx-js-hash))
|
|
;; Body scripts — configurable per app
|
|
;; Pass a list (even empty) to override defaults; nil = use defaults
|
|
(if (not (nil? body-scripts))
|
|
(map (fn (src) (script :src src)) body-scripts)
|
|
;; Default: body.js (legacy apps)
|
|
(script :src (str asset-url "/scripts/body.js?v=" body-js-hash)))))))
|