From 3369166a037d3548b211399078f7c0f5362c2429 Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 19 Jun 2026 20:35:57 +0000 Subject: [PATCH] =?UTF-8?q?host:=20per-block=20guarded=20render=20?= =?UTF-8?q?=E2=80=94=20editor=20posts=20never=20502,=20real=20prose=20show?= =?UTF-8?q?s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A post created with the editor stored sx_content containing components the host can't resolve: the legacy editor emits bare ~kg-md while the cards are ~kg_cards/kg-md (drift — not papered over with aliases). render-to-html threw on the undefined symbol and host/blog-render had no error handling -> handler crash -> 502 on a REAL post (/mddddd/). Fix: render each block of the (<> ...) fragment under its own guard via render-page (env-supplied). Real prose (p/h1/ul/...) renders; an unsupported or malformed block degrades to a
placeholder; a bad block never crashes the handler. Verified live: /mddddd/ + all junk posts now 200 (text shown, cards placeheld). Full kg-card rendering = follow-on (resolve the name drift / native editor). Co-Authored-By: Claude Opus 4.8 --- lib/host/blog.sx | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/lib/host/blog.sx b/lib/host/blog.sx index e0ecf755..6f4f3f7a 100644 --- a/lib/host/blog.sx +++ b/lib/host/blog.sx @@ -59,12 +59,30 @@ (host/blog-slugs)))) ;; ── render ────────────────────────────────────────────────────────── -;; A post's sx_content is SX element markup -> HTML via the component renderer. +;; A post's sx_content is SX element markup -> HTML via render-page (which supplies +;; the server env so components resolve + keyword attrs are kept). +;; +;; Rendered PER BLOCK and guarded: the editor wraps content in a (<> ...) fragment +;; of blocks, some of which the host can't render (the legacy editor emits bare +;; ~kg-md cards while the components are ~kg_cards/kg-md — drift we don't paper over +;; with aliases). Rendering each block under its own guard means the real prose +;; (p/h1/ul/...) shows and only the unsupported block degrades to a placeholder — +;; and a bad block never crashes the handler (-> 502). +(define host/blog--render-node + (fn (node) + (guard (e (true "
(unsupported block)
")) + (render-page node)))) (define host/blog-render (fn (record) (let ((sx (get record :sx-content))) (if (and sx (not (= sx ""))) - (render-to-html (parse sx)) + (let ((tree (guard (e (true nil)) (parse sx)))) + (cond + ((nil? tree) "

(unparseable content)

") + ((and (= (type-of tree) "list") (> (len tree) 0) + (= (str (first tree)) "<>")) + (join "" (map host/blog--render-node (rest tree)))) + (else (host/blog--render-node tree)))) (str "

(empty post)

"))))) (define host/blog--page (fn (title body)