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))))
|
||||
(else (host/blog--render-node tree))))
|
||||
(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
|
||||
(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 ───────────────────────────────────────────────────
|
||||
;; Post body is rendered per-block (a guarded HTML string) then injected raw.
|
||||
(define host/blog-post
|
||||
(fn (req)
|
||||
(let ((slug (dream-param req "slug")))
|
||||
(let ((r (host/blog-get slug)))
|
||||
(if r
|
||||
(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
|
||||
(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
|
||||
(fn (req)
|
||||
(let ((posts (host/blog-list)))
|
||||
(dream-html
|
||||
(host/blog--page "Blog"
|
||||
(str "<h1>Posts</h1>"
|
||||
(if (> (len posts) 0)
|
||||
(str "<ul>" (reduce host/blog--li "" posts) "</ul>")
|
||||
"<p>No posts yet.</p>")
|
||||
"<p><a href=\"/new\">+ New post</a></p>"))))))
|
||||
(let ((items
|
||||
(map
|
||||
(fn (p)
|
||||
(quasiquote
|
||||
(li (a :href (unquote (str "/" (get p :slug) "/"))
|
||||
(unquote (get p :title))))))
|
||||
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))))
|
||||
|
||||
;; ── create page (GET /new) — clean minimal form ────────────────────
|
||||
;; A plain create form: title + sx_content (SX element markup) + status. No
|
||||
;; legacy JS editor, no external assets, no shims. The rich WYSIWYG is a future
|
||||
;; 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.
|
||||
;; ── create page (GET /new) — clean minimal form as an SX tree ───────
|
||||
;; No legacy JS editor, no external assets, no shims. The rich WYSIWYG is a
|
||||
;; future native SX-island editor (Phase 5.2+). Posts to /new.
|
||||
(define host/blog-new-form
|
||||
(fn (req)
|
||||
(dream-html
|
||||
(host/blog--page "New post"
|
||||
(str
|
||||
"<h1>New post</h1>"
|
||||
"<form method=\"post\" action=\"/new\">"
|
||||
"<p><input name=\"title\" placeholder=\"Title\" style=\"font-size:1.4em;width:100%\"></p>"
|
||||
"<p><textarea name=\"sx_content\" rows=\"12\" style=\"width:100%;font-family:monospace\" "
|
||||
"placeholder=\"(p "Your post as SX markup")\"></textarea></p>"
|
||||
"<p><select name=\"status\"><option value=\"draft\">Draft</option>"
|
||||
"<option value=\"published\">Published</option></select> "
|
||||
"<button type=\"submit\">Publish</button></p>"
|
||||
"</form><p><a href=\"/\">← all posts</a></p>")))))
|
||||
(quasiquote
|
||||
(div
|
||||
(h1 "New post")
|
||||
(form :method "post" :action "/new"
|
||||
(p (input :name "title" :placeholder "Title"
|
||||
:style "font-size:1.4em;width:100%"))
|
||||
(p (textarea :name "sx_content" :rows "12"
|
||||
:style "width:100%;font-family:monospace"
|
||||
:placeholder "(p \"Your post as SX markup\")"))
|
||||
(p (select :name "status"
|
||||
(option :value "draft" "Draft")
|
||||
(option :value "published" "Published"))
|
||||
" "
|
||||
(button :type "submit" "Publish")))
|
||||
(p (a :href "/" "all posts"))))))))
|
||||
|
||||
;; ── write handlers ──────────────────────────────────────────────────
|
||||
;; POST /new — form-urlencoded ingest (the editor's submit shape: title,
|
||||
|
||||
Reference in New Issue
Block a user