diff --git a/lib/host/blog.sx b/lib/host/blog.sx index 53e610c5..a6ac57d9 100644 --- a/lib/host/blog.sx +++ b/lib/host/blog.sx @@ -84,57 +84,80 @@ (join "" (map host/blog--render-node (rest tree)))) (else (host/blog--render-node tree)))) (str "

(empty post)

"))))) +;; ── 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 "" title "" body))) + (str "" + (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 "

404

No published post: " slug "

")))))))) + (quasiquote + (div (h1 "404") + (p (unquote (str "No published post: " slug)))))))))))) -(define host/blog--li - (fn (acc p) - (str acc "
  • " (get p :title) "
  • "))) (define host/blog-home (fn (req) (let ((posts (host/blog-list))) - (dream-html - (host/blog--page "Blog" - (str "

    Posts

    " - (if (> (len posts) 0) - (str "") - "

    No posts yet.

    ") - "

    + New post

    ")))))) + (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 - "

    New post

    " - "
    " - "

    " - "

    " - "

    " - "

    " - "

    ← all posts

    "))))) + (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,