refactor(v0): render shell with hemplate

Move the v0 page shell from a Rust format! raw HTML string into a hemplate AppShell view and cover the rendered document structure with scraper.

req: html_safety/002

req: view/001

req: test/005
This commit is contained in:
slhx agent
2026-05-25 21:54:04 +02:00
parent f8d46e1a40
commit 58e96162d4
2 changed files with 46 additions and 22 deletions
+26 -22
View File
@@ -43,6 +43,11 @@ struct PageSwap {
title: &'static str, title: &'static str,
} }
#[derive(Hemplate)]
struct AppShell {
body: SafeHtml,
}
#[derive(Hemplate)] #[derive(Hemplate)]
#[hemplate = "partials"] #[hemplate = "partials"]
struct DocsContent { struct DocsContent {
@@ -180,28 +185,10 @@ fn all_examples() -> String {
} }
fn shell(body: String) -> String { fn shell(body: String) -> String {
format!( // req: html_safety/002 req: view/001
r#"<!doctype html> render_template(&AppShell {
<html lang="en"> body: SafeHtml::trusted(body),
<head> })
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>slhx v0 examples</title>
<script src="/slhx.js" defer></script>
<style>
body {{ font-family: system-ui, sans-serif; margin: 2rem; max-width: 54rem; }}
section, main {{ border: 1px solid #ddd; border-radius: .5rem; margin: 1rem 0; padding: 1rem; }}
input, button {{ font: inherit; margin: .25rem; }}
nav a {{ margin-right: .75rem; }}
</style>
</head>
<body>
<h1>slhx v0 browser examples</h1>
<p>Try the counter, todo form, wizard, login, page swap, and live SSE notifications.</p>
{body}
</body>
</html>"#
)
} }
fn render_todos(todos: &[Todo]) -> SafeHtml { fn render_todos(todos: &[Todo]) -> SafeHtml {
@@ -247,6 +234,23 @@ mod tests {
Selector::parse(value).expect("test selector parses") Selector::parse(value).expect("test selector parses")
} }
// req: html_safety/002 req: view/001 req: test/005
#[test]
fn shell_is_rendered_by_a_hemplate_view() {
let html = shell(render_page_swap("Welcome", "Welcome"));
let document = Html::parse_document(&html);
assert_eq!(
document
.select(&selector("title"))
.next()
.map(|title| title.text().collect::<String>()),
Some("slhx v0 examples".to_owned())
);
assert_eq!(document.select(&selector("script[src=\"/slhx.js\"]")).count(), 1);
assert_eq!(document.select(&selector("main[data-slhx-root=\"docs\"]")).count(), 1);
assert!(!html.contains("{+="));
}
// req: html_safety/002 req: view/001 req: test/005 // req: html_safety/002 req: view/001 req: test/005
#[test] #[test]
fn docs_content_payload_is_rendered_by_a_hemplate_view() { fn docs_content_payload_is_rendered_by_a_hemplate_view() {
+20
View File
@@ -0,0 +1,20 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>slhx v0 examples</title>
<script src="/slhx.js" defer></script>
<style>
body { font-family: system-ui, sans-serif; margin: 2rem; max-width: 54rem; }
section, main { border: 1px solid #ddd; border-radius: .5rem; margin: 1rem 0; padding: 1rem; }
input, button { font: inherit; margin: .25rem; }
nav a { margin-right: .75rem; }
</style>
</head>
<body>
<h1>slhx v0 browser examples</h1>
<p>Try the counter, todo form, wizard, login, page swap, and live SSE notifications.</p>
{+= self.body =+}
</body>
</html>