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
|
## Mental model: render → slot/key → effect → runtime
|
||||||
|
|
||||||
- **Render:** hemplate renders Rust view structs into checked HTML. App code
|
- **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
|
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
|
- **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
|
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:
|
For v1, document changes in three buckets:
|
||||||
|
|
||||||
- **Beginner API:** generated helpers, `#[hemx::app]`, `#[hemx::component]`,
|
- **Beginner API:** generated helpers, `#[hemx::app]`, `#[hemx::component]`,
|
||||||
`#[hemx::handler]`, `#[hemx::form]`, `hemx::page`, tuple `IntoEffect`, and
|
`#[hemx::handler]`, `#[hemx::form]`, generated page-boundary rendering, tuple
|
||||||
`Result<impl IntoEffect, E>` mapping. Breaking changes require a major version
|
`IntoEffect`, and `Result<impl IntoEffect, E>` mapping. Breaking changes
|
||||||
or an explicit migration note.
|
require a major version or an explicit migration note.
|
||||||
- **Wire/runtime ABI:** EffectBatch schema, runtime ABI version, and fingerprint
|
- **Wire/runtime ABI:** EffectBatch schema, runtime ABI version, and fingerprint
|
||||||
inputs. Incompatible changes must bump ABI versions and fail closed at runtime.
|
inputs. Incompatible changes must bump ABI versions and fail closed at runtime.
|
||||||
- **Advanced escape hatches:** raw effects, manual registries, low-level ids,
|
- **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]`,
|
- `#[hemx::surface]`, `#[hemx::app]`, `#[hemx::component]`, `#[hemx::handler]`,
|
||||||
and `#[hemx::form]`
|
and `#[hemx::form]`
|
||||||
- generated component helpers for slots, keyed partials, forms, handles, page
|
- generated component helpers for slots, keyed partials, forms, handles, page
|
||||||
targets, class tokens, and events
|
targets, page-boundary rendering, class tokens, and events
|
||||||
- `hemx::page(...)` for page-boundary rendering
|
- `hemx::page(...)` only at explicit server shell boundaries
|
||||||
- tuple `IntoEffect` composition
|
- tuple `IntoEffect` composition
|
||||||
- `Result<impl IntoEffect, E>` handlers with `IntoHandlerFailure`
|
- `Result<impl IntoEffect, E>` handlers with `IntoHandlerFailure`
|
||||||
- generated form commands such as `clear`, `reset`, `error`, and `focus`
|
- 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 {
|
pub fn page(runtime_src: &'static str, state: &WorkoutState) -> Html {
|
||||||
ui::render(&AppShell {
|
ui::page(&AppShell {
|
||||||
runtime_src,
|
runtime_src,
|
||||||
body: render(state),
|
body: render(state),
|
||||||
})
|
})
|
||||||
@@ -683,7 +683,7 @@ pub fn view(state: &WorkoutState) -> Workout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(state: &WorkoutState) -> Html {
|
pub fn render(state: &WorkoutState) -> Html {
|
||||||
ui::render(&view(state))
|
ui::page(&view(state))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
|
|||||||
@@ -743,6 +743,9 @@ impl Resources {
|
|||||||
"{pad} ::hemx::__private::html_trusted(lower(html))\n"
|
"{pad} ::hemx::__private::html_trusted(lower(html))\n"
|
||||||
));
|
));
|
||||||
out.push_str(&format!("{pad}}}\n\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}#[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}pub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html {{ render(view) }}\n\n"));
|
||||||
out.push_str(&format!("{pad}#[doc(hidden)]\n"));
|
out.push_str(&format!("{pad}#[doc(hidden)]\n"));
|
||||||
@@ -1733,6 +1736,7 @@ mod tests {
|
|||||||
assert!(
|
assert!(
|
||||||
generated.contains("pub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
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(
|
assert!(generated.contains(
|
||||||
"#[doc(hidden)]\npub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"
|
"#[doc(hidden)]\npub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"
|
||||||
));
|
));
|
||||||
@@ -1845,6 +1849,9 @@ mod tests {
|
|||||||
assert!(
|
assert!(
|
||||||
generated.contains("\npub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
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("\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 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"));
|
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 const todos: SlotTarget<::std::string::String> = SlotTarget::new(super::advanced::slots::todos);"));
|
||||||
assert!(generated.contains(" pub use self::targets::todos;"));
|
assert!(generated.contains(" pub use self::targets::todos;"));
|
||||||
assert!(generated.contains(" #[doc(hidden)]\n pub fn lower_html"));
|
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(" #[doc(hidden)]\n pub fn render_html(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"));
|
||||||
assert!(
|
assert!(
|
||||||
generated.contains(" pub fn static_fragment(html: &'static str) -> ::hemx::Html")
|
generated.contains(" pub fn static_fragment(html: &'static str) -> ::hemx::Html")
|
||||||
|
|||||||
Reference in New Issue
Block a user