feat(hemx): clarify generated authoring path

Close the fallible handler and example coherence slice: v0 uses typed todo newtypes, Result handler failure mapping, generated form/partial helpers, and page composition; kanban is explicitly marked as an advanced north-star milestone; raw render is isolated behind hemx::advanced::render.

req: canonical_authoring/003

req: failure/004

req: public_api/005

req: examples/004
This commit is contained in:
slhx agent
2026-06-05 08:36:39 +02:00
parent c33500440e
commit 53480dba5a
8 changed files with 536 additions and 110 deletions
+22 -11
View File
@@ -18,6 +18,10 @@ pub use hemx_derive::{app, component, form, handler, surface};
/// handles/forms/classes, `Html`, `IntoEffect`, and tuple composition. req: dx/001 req: public_api/005
pub mod advanced {
pub use hemx_core::*;
pub fn render(view: &impl hemplate::Hemplate) -> crate::Html {
crate::render_template(view)
}
}
/// Rendered, checked HTML produced by hemplate/hemx rendering helpers.
@@ -68,13 +72,17 @@ pub mod __private {
}
}
pub fn render(view: &impl hemplate::Hemplate) -> Html {
fn render_template(view: &impl hemplate::Hemplate) -> Html {
let mut html = String::new();
view.render_into(&mut html)
.expect("hemplate view renders into hemx effect payload");
__private::html_trusted(html)
}
pub fn page(view: &impl hemplate::Hemplate) -> Html {
render_template(view)
}
/// A hemplate partial that carries the stable key for a generated keyed target.
///
/// Generated keyed target helpers use this to keep ordinary handler code at the
@@ -86,7 +94,7 @@ pub trait KeyedPartial {
#[doc(hidden)]
pub fn render_html(view: &impl hemplate::Hemplate) -> Html {
render(view)
render_template(view)
}
/// Compatibility shim for raw slot rendering.
@@ -107,7 +115,7 @@ pub trait RenderSlotExt {
impl<T> RenderSlotExt for Slot<T> {
fn render(self, view: &impl hemplate::Hemplate) -> Effect {
self.html(render(view))
self.html(render_template(view))
}
}
@@ -148,21 +156,20 @@ where
K: ToString,
{
fn append(self, key: K, view: &impl hemplate::Hemplate) -> Effect {
self.append_html(key, render(view))
self.append_html(key, render_template(view))
}
fn prepend(self, key: K, view: &impl hemplate::Hemplate) -> Effect {
self.prepend_html(key, render(view))
self.prepend_html(key, render_template(view))
}
fn replace(self, key: K, view: &impl hemplate::Hemplate) -> Effect {
self.replace_html(key, render(view))
self.replace_html(key, render_template(view))
}
}
pub mod prelude {
pub use crate::render;
pub use crate::Html;
pub use crate::{page, Html};
pub use hemx_core::{
navigate, push, redirect, replace, Atom, ComponentRef, CssClass, CssClasses, EventName,
Form, FormModel, FormValue, Handle, IntoEffect, ParamName,
@@ -182,13 +189,17 @@ mod tests {
}
#[test]
fn render_is_the_short_safe_html_helper() {
fn page_is_the_short_safe_html_helper() {
// req: dx/006 req: html_safety/002
assert_eq!(crate::render(&InlineView).as_str(), "<strong>ok</strong>");
assert_eq!(crate::page(&InlineView).as_str(), "<strong>ok</strong>");
assert_eq!(
crate::render_html(&InlineView).as_str(),
"<strong>ok</strong>"
);
assert_eq!(
crate::advanced::render(&InlineView).as_str(),
"<strong>ok</strong>"
);
}
#[test]
@@ -196,7 +207,7 @@ mod tests {
// req: dx/006 req: public_api/005 req: html_safety/002
use crate::prelude::*;
let html = Html::join([render(&InlineView)]);
let html = Html::join([page(&InlineView)]);
assert_eq!(html.as_str(), "<strong>ok</strong>");
}