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:
+10
-10
@@ -111,7 +111,7 @@ async fn main() {
|
||||
async fn home(State(state): State<Arc<AppState>>, request: PageRequest) -> impl IntoResponse {
|
||||
let board = state.board.lock().unwrap().clone();
|
||||
request
|
||||
.page(page_html(&board), shell)
|
||||
.page_html(page_html(&board), shell)
|
||||
.title("slhx Kanban")
|
||||
.fingerprint(ui::BUILD_FINGERPRINT)
|
||||
}
|
||||
@@ -223,18 +223,18 @@ fn parse_column(value: Option<&str>) -> usize {
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
fn page_html(board: &BoardState) -> String {
|
||||
// Explicit full-page composition boundary for already-rendered hemplate fragments.
|
||||
fn page_html(board: &BoardState) -> SafeHtml {
|
||||
// req: html_safety/002 req: view/001
|
||||
board_ui::render(&Board {
|
||||
options: render_options(),
|
||||
board: ui::render(&board_view(board)),
|
||||
})
|
||||
.into_string()
|
||||
}
|
||||
|
||||
fn shell(body: String) -> String {
|
||||
format!(
|
||||
fn shell(body: SafeHtml) -> SafeHtml {
|
||||
// Explicit full-page composition boundary for already-rendered hemplate fragments.
|
||||
// req: html_safety/001 req: html_safety/002 req: axum_integration/001
|
||||
SafeHtml::trusted(format!(
|
||||
r#"<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
@@ -257,7 +257,7 @@ fn shell(body: String) -> String {
|
||||
{body}
|
||||
</body>
|
||||
</html>"#
|
||||
)
|
||||
))
|
||||
}
|
||||
|
||||
fn render_options() -> SafeHtml {
|
||||
@@ -311,10 +311,10 @@ mod tests {
|
||||
#[test]
|
||||
fn kanban_page_is_composed_by_a_hemplate_view() {
|
||||
let html = page_html(&BoardState::default());
|
||||
assert!(!html.contains("__OPTIONS__"));
|
||||
assert!(!html.contains("__BOARD__"));
|
||||
assert!(!html.as_str().contains("__OPTIONS__"));
|
||||
assert!(!html.as_str().contains("__BOARD__"));
|
||||
|
||||
let document = Html::parse_fragment(&html);
|
||||
let document = Html::parse_fragment(html.as_str());
|
||||
assert_eq!(document.select(&selector("section[data-slhx-root=\"kanban\"]")).count(), 1);
|
||||
assert_eq!(document.select(&selector("select[name=\"column\"] > option")).count(), 3);
|
||||
assert_eq!(document.select(&selector("[data-sid]")).count(), 3);
|
||||
|
||||
Reference in New Issue
Block a user