host: Slice 8c render-template-per-type + metamodel create-type form
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 24s
Closes the 'types define the UI' loop and adds the editor's create half. 8c (render template): a type declares a :template — a parameterised SX tree (stored as source) with (field "name") placeholders that resolve to the instance's field-values at render. host/blog-template-of / --set-template! / --instantiate (pure tree-walk) / --typed-block (per the post's types, parse+instantiate, pre-fetched in the handler). host/blog-post renders it above the body. Article seeded a subtitle standfirst template. So ONE field definition now drives BOTH the edit form AND the rendered page. create-type (metamodel editor surface 1): POST /meta/new-type creates a published post subtype-of "type" -> appears in host/blog-type-defs / the /meta Types list, ready to be given fields/schema/template. Guarded (unauthed -> login, not created). /meta gains a '+ Type' form. You can now DEFINE A TYPE THROUGH THE UI. Verified live-path: typed post's subtitle renders on its page; create 'Recipe' via the form -> Types(4). Blog suite 140/140. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -651,6 +651,39 @@
|
||||
(list (get (host/blog-field-values-of "fpost") "subtitle")
|
||||
(get (host/blog-field-values-of "fpost") "hero")))
|
||||
(list "Saved Sub" "http://z/q.png"))
|
||||
|
||||
;; -- Slice 8c: render template per type (fields drive the page too) --
|
||||
(host-bl-test "instantiate resolves (field name), replacing the placeholder"
|
||||
(list (contains? (str (host/blog--instantiate (parse-safe "(p (field \"subtitle\"))") {"subtitle" "Hi"})) "Hi")
|
||||
(contains? (str (host/blog--instantiate (parse-safe "(p (field \"x\"))") {})) "field"))
|
||||
(list true false))
|
||||
(host-bl-test "template-of reads the article's seeded render template"
|
||||
(contains? (host/blog-template-of "article") "field") true)
|
||||
(host-bl-test "typed-block renders a typed post's field values"
|
||||
(begin
|
||||
(host/blog--set-field-values! "fpost" {"subtitle" "My Standfirst" "hero" ""})
|
||||
(contains? (str (host/blog--typed-block "fpost")) "My Standfirst"))
|
||||
true)
|
||||
(host-bl-test "typed-block is empty for an untyped post"
|
||||
(host/blog--typed-block "hello") "")
|
||||
(host-bl-test "post page renders the typed template standfirst"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/fpost/"))) "My Standfirst") true)
|
||||
|
||||
;; -- metamodel editor: define a type through the UI (POST /meta/new-type) --
|
||||
(host-bl-test "/meta has the create-type form"
|
||||
(contains? (dream-resp-body (host-bl-app (host-bl-req "/meta"))) "/meta/new-type") true)
|
||||
(host-bl-test "POST /meta/new-type creates a type (subtype-of type) in type-defs"
|
||||
(begin
|
||||
(host-bl-wapp (host-bl-send "POST" "/meta/new-type" "Bearer good"
|
||||
"application/x-www-form-urlencoded" "title=Recipe"))
|
||||
(list (host/blog-exists? "recipe") (contains? (host/blog-type-defs) "recipe")))
|
||||
(list true true))
|
||||
(host-bl-test "create-type requires auth (unauthed -> not created)"
|
||||
(begin
|
||||
(host-bl-wapp (host-bl-send "POST" "/meta/new-type" nil
|
||||
"application/x-www-form-urlencoded" "title=Sneaky Type"))
|
||||
(host/blog-exists? "sneaky-type"))
|
||||
false)
|
||||
(host-bl-test "a post with no schema'd type is vacuously valid"
|
||||
(host/blog-type-valid? "ppost" "(p \"anything\")") true)
|
||||
(host-bl-test "edit-submit rejects content violating the type schema (not saved)"
|
||||
|
||||
Reference in New Issue
Block a user