feat(build): generate page-boundary helper
Expose generated ui::page as the canonical page-boundary rendering helper and move the Workout golden path and docs off beginner-visible ui::render calls. req: public_api/002 req: codegen/002 req: canonical_authoring/006
This commit is contained in:
@@ -34,7 +34,7 @@ For beginner and production-shaped app code, stay on this path. req: public_api/
|
||||
## Mental model: render → slot/key → effect → runtime
|
||||
|
||||
- **Render:** hemplate renders Rust view structs into checked HTML. App code
|
||||
normally reaches rendering through generated helpers or `hemx::page(...)` at a
|
||||
normally reaches rendering through generated `ui::page(...)` helpers at a
|
||||
server page boundary, not raw HTML construction. req: html_safety/002 req: view/001
|
||||
- **Slot/key:** a generated slot names the target, and a generated keyed slot
|
||||
also carries the stable row key. A list target inside `h-for` must have a
|
||||
|
||||
@@ -99,9 +99,9 @@ persistence or cross-version addressing contract. req: abi/005
|
||||
For v1, document changes in three buckets:
|
||||
|
||||
- **Beginner API:** generated helpers, `#[hemx::app]`, `#[hemx::component]`,
|
||||
`#[hemx::handler]`, `#[hemx::form]`, `hemx::page`, tuple `IntoEffect`, and
|
||||
`Result<impl IntoEffect, E>` mapping. Breaking changes require a major version
|
||||
or an explicit migration note.
|
||||
`#[hemx::handler]`, `#[hemx::form]`, generated page-boundary rendering, tuple
|
||||
`IntoEffect`, and `Result<impl IntoEffect, E>` mapping. Breaking changes
|
||||
require a major version or an explicit migration note.
|
||||
- **Wire/runtime ABI:** EffectBatch schema, runtime ABI version, and fingerprint
|
||||
inputs. Incompatible changes must bump ABI versions and fail closed at runtime.
|
||||
- **Advanced escape hatches:** raw effects, manual registries, low-level ids,
|
||||
|
||||
+2
-2
@@ -15,8 +15,8 @@ changes:
|
||||
- `#[hemx::surface]`, `#[hemx::app]`, `#[hemx::component]`, `#[hemx::handler]`,
|
||||
and `#[hemx::form]`
|
||||
- generated component helpers for slots, keyed partials, forms, handles, page
|
||||
targets, class tokens, and events
|
||||
- `hemx::page(...)` for page-boundary rendering
|
||||
targets, page-boundary rendering, class tokens, and events
|
||||
- `hemx::page(...)` only at explicit server shell boundaries
|
||||
- tuple `IntoEffect` composition
|
||||
- `Result<impl IntoEffect, E>` handlers with `IntoHandlerFailure`
|
||||
- generated form commands such as `clear`, `reset`, `error`, and `focus`
|
||||
|
||||
@@ -627,7 +627,7 @@ pub struct AppShell {
|
||||
}
|
||||
|
||||
pub fn page(runtime_src: &'static str, state: &WorkoutState) -> Html {
|
||||
ui::render(&AppShell {
|
||||
ui::page(&AppShell {
|
||||
runtime_src,
|
||||
body: render(state),
|
||||
})
|
||||
@@ -683,7 +683,7 @@ pub fn view(state: &WorkoutState) -> Workout {
|
||||
}
|
||||
|
||||
pub fn render(state: &WorkoutState) -> Html {
|
||||
ui::render(&view(state))
|
||||
ui::page(&view(state))
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
||||
@@ -743,6 +743,9 @@ impl Resources {
|
||||
"{pad} ::hemx::__private::html_trusted(lower(html))\n"
|
||||
));
|
||||
out.push_str(&format!("{pad}}}\n\n"));
|
||||
out.push_str(&format!(
|
||||
"{pad}pub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html {{ render(view) }}\n\n"
|
||||
));
|
||||
out.push_str(&format!("{pad}#[doc(hidden)]\n"));
|
||||
out.push_str(&format!("{pad}pub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html {{ render(view) }}\n\n"));
|
||||
out.push_str(&format!("{pad}#[doc(hidden)]\n"));
|
||||
@@ -1733,6 +1736,7 @@ mod tests {
|
||||
assert!(
|
||||
generated.contains("pub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
||||
);
|
||||
assert!(generated.contains("pub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"));
|
||||
assert!(generated.contains(
|
||||
"#[doc(hidden)]\npub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"
|
||||
));
|
||||
@@ -1845,6 +1849,9 @@ mod tests {
|
||||
assert!(
|
||||
generated.contains("\npub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
||||
);
|
||||
assert!(
|
||||
generated.contains("\npub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
||||
);
|
||||
assert!(generated.contains("\n#[doc(hidden)]\npub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"));
|
||||
assert!(generated.contains("\npub fn put<T>(slot: ::hemx::advanced::Slot<T>, view: &impl ::hemplate::Hemplate) -> ::hemx::advanced::Effect"));
|
||||
assert!(generated.contains("\npub fn append<K, T>(slot: ::hemx::advanced::KeyedSlot<K, T>, key: K, view: &impl ::hemplate::Hemplate) -> ::hemx::advanced::Effect"));
|
||||
@@ -1858,6 +1865,9 @@ mod tests {
|
||||
assert!(generated.contains(" pub const todos: SlotTarget<::std::string::String> = SlotTarget::new(super::advanced::slots::todos);"));
|
||||
assert!(generated.contains(" pub use self::targets::todos;"));
|
||||
assert!(generated.contains(" #[doc(hidden)]\n pub fn lower_html"));
|
||||
assert!(
|
||||
generated.contains(" pub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
||||
);
|
||||
assert!(generated.contains(" #[doc(hidden)]\n pub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"));
|
||||
assert!(
|
||||
generated.contains(" pub fn static_fragment(html: &'static str) -> ::hemx::Html")
|
||||
|
||||
Reference in New Issue
Block a user