feat(axum): add safe html page composition
Add a SafeHtml PageRequest path for shell/partial composition and migrate examples so rendered hemplate fragments stay typed through the transport boundary instead of round-tripping through unchecked strings. req: axum_integration/001 req: html_safety/001 req: html_safety/002
This commit is contained in:
+22
-23
@@ -80,7 +80,7 @@ async fn main() {
|
||||
// req: examples/001
|
||||
async fn home(request: PageRequest) -> impl IntoResponse {
|
||||
request
|
||||
.page(all_examples(), shell)
|
||||
.page_html(all_examples(), shell)
|
||||
.title("slhx v0 examples")
|
||||
.fingerprint(ui::BUILD_FINGERPRINT)
|
||||
}
|
||||
@@ -89,7 +89,7 @@ async fn home(request: PageRequest) -> impl IntoResponse {
|
||||
async fn docs(request: PageRequest) -> impl IntoResponse {
|
||||
let partial = render_page_swap("Docs", "This page was swapped without a full reload.");
|
||||
request
|
||||
.page(partial, shell)
|
||||
.page_html(partial, shell)
|
||||
.title("Docs")
|
||||
.fingerprint(ui::BUILD_FINGERPRINT)
|
||||
}
|
||||
@@ -179,25 +179,25 @@ fn registry(state: Arc<ExampleState>) -> HandlerRegistry {
|
||||
})
|
||||
}
|
||||
|
||||
fn all_examples() -> String {
|
||||
[
|
||||
counter::lower(include_str!("../templates/counter.heml")),
|
||||
todos::lower(include_str!("../templates/todos.heml")),
|
||||
wizard::lower(include_str!("../templates/wizard.heml")),
|
||||
auth::lower(include_str!("../templates/auth.heml")),
|
||||
render_page_swap("Welcome", "Welcome"),
|
||||
notifications::lower(include_str!("../templates/notifications.heml")),
|
||||
]
|
||||
.join("\n")
|
||||
fn all_examples() -> SafeHtml {
|
||||
// Static `.heml` fragments are lowered by generated code before they join rendered views.
|
||||
// req: html_safety/001 req: html_safety/002 req: component/003
|
||||
SafeHtml::trusted(
|
||||
[
|
||||
counter::lower(include_str!("../templates/counter.heml")),
|
||||
todos::lower(include_str!("../templates/todos.heml")),
|
||||
wizard::lower(include_str!("../templates/wizard.heml")),
|
||||
auth::lower(include_str!("../templates/auth.heml")),
|
||||
render_page_swap("Welcome", "Welcome").into_string(),
|
||||
notifications::lower(include_str!("../templates/notifications.heml")),
|
||||
]
|
||||
.join("\n"),
|
||||
)
|
||||
}
|
||||
|
||||
fn shell(body: String) -> String {
|
||||
// Explicit full-page shell composition boundary for already-rendered hemplate fragments.
|
||||
// req: html_safety/002 req: view/001 req: component/003
|
||||
ui::render(&AppShell {
|
||||
body: SafeHtml::trusted(body),
|
||||
})
|
||||
.into_string()
|
||||
fn shell(body: SafeHtml) -> SafeHtml {
|
||||
// req: html_safety/001 req: html_safety/002 req: axum_integration/001 req: component/003
|
||||
ui::render(&AppShell { body })
|
||||
}
|
||||
|
||||
fn todos_view(todos: &[Todo]) -> TodoItems {
|
||||
@@ -213,13 +213,12 @@ fn todos_view(todos: &[Todo]) -> TodoItems {
|
||||
}
|
||||
}
|
||||
|
||||
fn render_page_swap(title: &'static str, message: &'static str) -> String {
|
||||
fn render_page_swap(title: &'static str, message: &'static str) -> SafeHtml {
|
||||
// req: html_safety/002 req: view/001 req: component/003
|
||||
page_swap::render(&PageSwap {
|
||||
content: render_docs_content(message),
|
||||
title,
|
||||
})
|
||||
.into_string()
|
||||
}
|
||||
|
||||
fn render_docs_content(message: &'static str) -> SafeHtml {
|
||||
@@ -240,7 +239,7 @@ mod tests {
|
||||
#[test]
|
||||
fn shell_is_rendered_by_a_hemplate_view() {
|
||||
let html = shell(render_page_swap("Welcome", "Welcome"));
|
||||
let document = Html::parse_document(&html);
|
||||
let document = Html::parse_document(html.as_str());
|
||||
assert_eq!(
|
||||
document
|
||||
.select(&selector("title"))
|
||||
@@ -281,7 +280,7 @@ mod tests {
|
||||
#[test]
|
||||
fn docs_page_partial_is_rendered_by_a_hemplate_view() {
|
||||
let html = render_page_swap("Docs", "This page was swapped without a full reload.");
|
||||
let document = Html::parse_fragment(&html);
|
||||
let document = Html::parse_fragment(html.as_str());
|
||||
assert_eq!(document.select(&selector("main[data-slhx-root=\"docs\"]")).count(), 1);
|
||||
assert_eq!(document.select(&selector("article[data-sid]")).count(), 1);
|
||||
assert_eq!(
|
||||
|
||||
Reference in New Issue
Block a user