host: blog pages as SX trees + render-page (no embedded HTML)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 18s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 18s
The handler runs the dynamic logic in the full evaluator and builds a static SX element tree via quasiquote; render-page (5.1) renders it. No aser pipeline needed for server-rendered pages. host/blog--page is now an (html (head..)(body..)) tree; home builds the posts <ul> via map+quasiquote; the post body is rendered per-block then injected with (raw! ...); /new is an SX form tree. Only the doctype prefix remains as a string (render-to-html doesn't emit it). 181/181. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -84,57 +84,80 @@
|
|||||||
(join "" (map host/blog--render-node (rest tree))))
|
(join "" (map host/blog--render-node (rest tree))))
|
||||||
(else (host/blog--render-node tree))))
|
(else (host/blog--render-node tree))))
|
||||||
(str "<p>(empty post)</p>")))))
|
(str "<p>(empty post)</p>")))))
|
||||||
|
;; ── page shell ──────────────────────────────────────────────────────
|
||||||
|
;; A page is an SX element tree, rendered via render-page (5.1). The handler
|
||||||
|
;; builds the tree (running any dynamic logic in the full evaluator, e.g. a posts
|
||||||
|
;; loop) and render-page renders the static result — no embedded HTML strings,
|
||||||
|
;; only the doctype prefix render-to-html doesn't emit. `body` is an SX node.
|
||||||
(define host/blog--page
|
(define host/blog--page
|
||||||
(fn (title body)
|
(fn (title body)
|
||||||
(str "<!doctype html><meta charset=\"utf-8\"><title>" title "</title>" body)))
|
(str "<!doctype html>"
|
||||||
|
(render-page
|
||||||
|
(quasiquote
|
||||||
|
(html
|
||||||
|
(head (meta :charset "utf-8") (title (unquote title)))
|
||||||
|
(body (unquote body))))))))
|
||||||
|
|
||||||
;; ── read handlers ───────────────────────────────────────────────────
|
;; ── read handlers ───────────────────────────────────────────────────
|
||||||
|
;; Post body is rendered per-block (a guarded HTML string) then injected raw.
|
||||||
(define host/blog-post
|
(define host/blog-post
|
||||||
(fn (req)
|
(fn (req)
|
||||||
(let ((slug (dream-param req "slug")))
|
(let ((slug (dream-param req "slug")))
|
||||||
(let ((r (host/blog-get slug)))
|
(let ((r (host/blog-get slug)))
|
||||||
(if r
|
(if r
|
||||||
(dream-html
|
(dream-html
|
||||||
(host/blog--page (get r :title) (host/blog-render r)))
|
(host/blog--page (get r :title)
|
||||||
|
(quasiquote (article (raw! (unquote (host/blog-render r)))))))
|
||||||
(dream-html-status 404
|
(dream-html-status 404
|
||||||
(host/blog--page "Not found"
|
(host/blog--page "Not found"
|
||||||
(str "<h1>404</h1><p>No published post: " slug "</p>"))))))))
|
(quasiquote
|
||||||
|
(div (h1 "404")
|
||||||
|
(p (unquote (str "No published post: " slug))))))))))))
|
||||||
|
|
||||||
(define host/blog--li
|
|
||||||
(fn (acc p)
|
|
||||||
(str acc "<li><a href=\"/" (get p :slug) "/\">" (get p :title) "</a></li>")))
|
|
||||||
(define host/blog-home
|
(define host/blog-home
|
||||||
(fn (req)
|
(fn (req)
|
||||||
(let ((posts (host/blog-list)))
|
(let ((posts (host/blog-list)))
|
||||||
(dream-html
|
(let ((items
|
||||||
(host/blog--page "Blog"
|
(map
|
||||||
(str "<h1>Posts</h1>"
|
(fn (p)
|
||||||
(if (> (len posts) 0)
|
(quasiquote
|
||||||
(str "<ul>" (reduce host/blog--li "" posts) "</ul>")
|
(li (a :href (unquote (str "/" (get p :slug) "/"))
|
||||||
"<p>No posts yet.</p>")
|
(unquote (get p :title))))))
|
||||||
"<p><a href=\"/new\">+ New post</a></p>"))))))
|
posts)))
|
||||||
|
(let ((listing (if (> (len posts) 0)
|
||||||
|
(list (quote ul) items)
|
||||||
|
(quote (p "No posts yet.")))))
|
||||||
|
(dream-html
|
||||||
|
(host/blog--page "Blog"
|
||||||
|
(quasiquote
|
||||||
|
(div (h1 "Posts")
|
||||||
|
(unquote listing)
|
||||||
|
(p (a :href "/new" "+ New post")))))))))))
|
||||||
|
|
||||||
(define host/blog-index (fn (req) (host/ok (host/blog-list))))
|
(define host/blog-index (fn (req) (host/ok (host/blog-list))))
|
||||||
|
|
||||||
;; ── create page (GET /new) — clean minimal form ────────────────────
|
;; ── create page (GET /new) — clean minimal form as an SX tree ───────
|
||||||
;; A plain create form: title + sx_content (SX element markup) + status. No
|
;; No legacy JS editor, no external assets, no shims. The rich WYSIWYG is a
|
||||||
;; legacy JS editor, no external assets, no shims. The rich WYSIWYG is a future
|
;; future native SX-island editor (Phase 5.2+). Posts to /new.
|
||||||
;; native SX-island editor served via the Phase-5.2 SSR pipeline (render-page
|
|
||||||
;; alone can't render dynamic-logic component bodies — proven). Posts to /new.
|
|
||||||
(define host/blog-new-form
|
(define host/blog-new-form
|
||||||
(fn (req)
|
(fn (req)
|
||||||
(dream-html
|
(dream-html
|
||||||
(host/blog--page "New post"
|
(host/blog--page "New post"
|
||||||
(str
|
(quasiquote
|
||||||
"<h1>New post</h1>"
|
(div
|
||||||
"<form method=\"post\" action=\"/new\">"
|
(h1 "New post")
|
||||||
"<p><input name=\"title\" placeholder=\"Title\" style=\"font-size:1.4em;width:100%\"></p>"
|
(form :method "post" :action "/new"
|
||||||
"<p><textarea name=\"sx_content\" rows=\"12\" style=\"width:100%;font-family:monospace\" "
|
(p (input :name "title" :placeholder "Title"
|
||||||
"placeholder=\"(p "Your post as SX markup")\"></textarea></p>"
|
:style "font-size:1.4em;width:100%"))
|
||||||
"<p><select name=\"status\"><option value=\"draft\">Draft</option>"
|
(p (textarea :name "sx_content" :rows "12"
|
||||||
"<option value=\"published\">Published</option></select> "
|
:style "width:100%;font-family:monospace"
|
||||||
"<button type=\"submit\">Publish</button></p>"
|
:placeholder "(p \"Your post as SX markup\")"))
|
||||||
"</form><p><a href=\"/\">← all posts</a></p>")))))
|
(p (select :name "status"
|
||||||
|
(option :value "draft" "Draft")
|
||||||
|
(option :value "published" "Published"))
|
||||||
|
" "
|
||||||
|
(button :type "submit" "Publish")))
|
||||||
|
(p (a :href "/" "all posts"))))))))
|
||||||
|
|
||||||
;; ── write handlers ──────────────────────────────────────────────────
|
;; ── write handlers ──────────────────────────────────────────────────
|
||||||
;; POST /new — form-urlencoded ingest (the editor's submit shape: title,
|
;; POST /new — form-urlencoded ingest (the editor's submit shape: title,
|
||||||
|
|||||||
Reference in New Issue
Block a user