feat(build): make generated page helper canonical
Move canonical examples and docs snippets from raw render/page calls to generated ui::page helpers, hide generated render behind doc(hidden), and let form resources participate in generated target inspection for tests. req: canonical_authoring/005 req: dx/006 req: codegen/002 req: public_api/002 req: test/001
This commit is contained in:
+1
-1
@@ -94,7 +94,7 @@ use ui::board::{forms, targets};
|
|||||||
|
|
||||||
targets::card.replace(card.id, &CardView::from(card));
|
targets::card.replace(card.id, &CardView::from(card));
|
||||||
forms::create_card.clear("title");
|
forms::create_card.clear("title");
|
||||||
ui::render(&BoardView::from(board));
|
ui::page(&BoardView::from(board));
|
||||||
```
|
```
|
||||||
|
|
||||||
No string desync. No manual ids. The generated module owns the names.
|
No string desync. No manual ids. The generated module owns the names.
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ mod tests {
|
|||||||
// req: html_safety/002 req: view/001 req: test/005
|
// req: html_safety/002 req: view/001 req: test/005
|
||||||
#[test]
|
#[test]
|
||||||
fn kanban_board_test_payload_is_rendered_by_a_hemplate_view() {
|
fn kanban_board_test_payload_is_rendered_by_a_hemplate_view() {
|
||||||
let html = super::ui::render(&empty_board());
|
let html = super::ui::page(&empty_board());
|
||||||
let document = Html::parse_fragment(html.as_str());
|
let document = Html::parse_fragment(html.as_str());
|
||||||
assert_eq!(document.select(&selector(".columns")).count(), 1);
|
assert_eq!(document.select(&selector(".columns")).count(), 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -281,15 +281,15 @@ fn parse_column(value: Option<&str>) -> usize {
|
|||||||
|
|
||||||
fn page_html(board: &BoardState) -> Html {
|
fn page_html(board: &BoardState) -> Html {
|
||||||
// req: html_safety/002 req: view/001
|
// req: html_safety/002 req: view/001
|
||||||
board_ui::render(&Board {
|
board_ui::page(&Board {
|
||||||
options: render_options(),
|
options: render_options(),
|
||||||
board: ui::render(&board_view(board)),
|
board: ui::page(&board_view(board)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shell(body: Html) -> Html {
|
fn shell(body: Html) -> Html {
|
||||||
// req: html_safety/001 req: html_safety/002 req: axum_integration/001
|
// req: html_safety/001 req: html_safety/002 req: axum_integration/001
|
||||||
hemx::page(&AppShell {
|
ui::page(&AppShell {
|
||||||
runtime_src: runtime_js_path(),
|
runtime_src: runtime_js_path(),
|
||||||
body,
|
body,
|
||||||
})
|
})
|
||||||
@@ -297,7 +297,7 @@ fn shell(body: Html) -> Html {
|
|||||||
|
|
||||||
fn render_options() -> Html {
|
fn render_options() -> Html {
|
||||||
// req: html_safety/002 req: view/001
|
// req: html_safety/002 req: view/001
|
||||||
ui::render(&ColumnOptions {
|
ui::page(&ColumnOptions {
|
||||||
options: COLUMNS
|
options: COLUMNS
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(id, title)| ColumnOption { id, title })
|
.map(|(id, title)| ColumnOption { id, title })
|
||||||
@@ -385,7 +385,7 @@ mod tests {
|
|||||||
}],
|
}],
|
||||||
};
|
};
|
||||||
|
|
||||||
let html = ui::render(&board_view(&board));
|
let html = ui::page(&board_view(&board));
|
||||||
let document = Html::parse_fragment(html.as_str());
|
let document = Html::parse_fragment(html.as_str());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
document
|
document
|
||||||
@@ -417,7 +417,7 @@ mod tests {
|
|||||||
// req: html_safety/002 req: view/001 req: test/005
|
// req: html_safety/002 req: view/001 req: test/005
|
||||||
#[test]
|
#[test]
|
||||||
fn presence_payload_is_rendered_by_a_hemplate_view() {
|
fn presence_payload_is_rendered_by_a_hemplate_view() {
|
||||||
let html = ui::render(&Presence { count: 7 });
|
let html = ui::page(&Presence { count: 7 });
|
||||||
let document = Html::parse_fragment(html.as_str());
|
let document = Html::parse_fragment(html.as_str());
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
document
|
document
|
||||||
|
|||||||
+15
-19
@@ -254,18 +254,18 @@ pub struct AppShell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn home_page(ctx: &AppContext) -> Html {
|
pub fn home_page(ctx: &AppContext) -> Html {
|
||||||
hemx::page(&AppShell {
|
ui::page(&AppShell {
|
||||||
title: "hemx SaaS tutorial",
|
title: "hemx SaaS tutorial",
|
||||||
runtime_src: runtime_js_path(),
|
runtime_src: runtime_js_path(),
|
||||||
body: hemx::page(&Dashboard::from_context(ctx)),
|
body: ui::page(&Dashboard::from_context(ctx)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn settings_page(ctx: &AppContext) -> Html {
|
pub fn settings_page(ctx: &AppContext) -> Html {
|
||||||
hemx::page(&AppShell {
|
ui::page(&AppShell {
|
||||||
title: "hemx SaaS tutorial settings",
|
title: "hemx SaaS tutorial settings",
|
||||||
runtime_src: runtime_js_path(),
|
runtime_src: runtime_js_path(),
|
||||||
body: hemx::page(&Dashboard::settings(ctx)),
|
body: ui::page(&Dashboard::settings(ctx)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,7 +330,7 @@ fn project_summary(total: usize) -> String {
|
|||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use hemx_axum::{InteractionForm, InteractionRequest};
|
use hemx_axum::{InteractionForm, InteractionRequest};
|
||||||
use hemx_test::{inspect, inspect_batch};
|
use hemx_test::{any_root_selector, inspect, inspect_batch, target_selector};
|
||||||
use scraper::{Html as ParsedHtml, Selector};
|
use scraper::{Html as ParsedHtml, Selector};
|
||||||
|
|
||||||
fn form<I>(handle: hemx::Handle<I>, fields: &[(&str, &str)]) -> InteractionForm {
|
fn form<I>(handle: hemx::Handle<I>, fields: &[(&str, &str)]) -> InteractionForm {
|
||||||
@@ -353,15 +353,13 @@ mod tests {
|
|||||||
let html = home_page(&ctx);
|
let html = home_page(&ctx);
|
||||||
let document = ParsedHtml::parse_document(html.as_str());
|
let document = ParsedHtml::parse_document(html.as_str());
|
||||||
|
|
||||||
|
assert_eq!(document.select(&selector(any_root_selector())).count(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
document
|
document
|
||||||
.select(&selector("[data-hemx-root='dashboard']"))
|
.select(&selector(&format!(
|
||||||
.count(),
|
"form{}",
|
||||||
1
|
target_selector(dashboard::new_project)
|
||||||
);
|
)))
|
||||||
assert_eq!(
|
|
||||||
document
|
|
||||||
.select(&selector("form[data-hemx-form='new_project']"))
|
|
||||||
.count(),
|
.count(),
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
@@ -389,15 +387,13 @@ mod tests {
|
|||||||
let html = settings_page(&ctx);
|
let html = settings_page(&ctx);
|
||||||
let document = ParsedHtml::parse_document(html.as_str());
|
let document = ParsedHtml::parse_document(html.as_str());
|
||||||
|
|
||||||
|
assert_eq!(document.select(&selector(any_root_selector())).count(), 1);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
document
|
document
|
||||||
.select(&selector("[data-hemx-root='dashboard']"))
|
.select(&selector(&format!(
|
||||||
.count(),
|
"{} .settings-page",
|
||||||
1
|
target_selector(dashboard::page_panel)
|
||||||
);
|
)))
|
||||||
assert_eq!(
|
|
||||||
document
|
|
||||||
.select(&selector("[data-hemx-slot='page_panel'] .settings-page"))
|
|
||||||
.count(),
|
.count(),
|
||||||
1
|
1
|
||||||
);
|
);
|
||||||
|
|||||||
+10
-10
@@ -268,18 +268,18 @@ fn registry(state: Arc<ExampleState>) -> Registry {
|
|||||||
fn all_examples() -> Html {
|
fn all_examples() -> Html {
|
||||||
// req: html_safety/001 req: html_safety/002 req: component/003
|
// req: html_safety/001 req: html_safety/002 req: component/003
|
||||||
Html::join([
|
Html::join([
|
||||||
counter::render(&Counter),
|
counter::page(&Counter),
|
||||||
hemx::page(&todos_view(&[])),
|
ui::page(&todos_view(&[])),
|
||||||
wizard::render(&Wizard),
|
wizard::page(&Wizard),
|
||||||
auth::render(&Auth),
|
auth::page(&Auth),
|
||||||
render_page_swap("Welcome", "Welcome"),
|
render_page_swap("Welcome", "Welcome"),
|
||||||
notifications::render(&Notifications),
|
notifications::page(&Notifications),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn shell(body: Html) -> Html {
|
fn shell(body: Html) -> Html {
|
||||||
// req: html_safety/001 req: html_safety/002 req: axum_integration/001 req: component/003
|
// req: html_safety/001 req: html_safety/002 req: axum_integration/001 req: component/003
|
||||||
hemx::page(&AppShell {
|
ui::page(&AppShell {
|
||||||
runtime_src: runtime_js_path(),
|
runtime_src: runtime_js_path(),
|
||||||
body,
|
body,
|
||||||
})
|
})
|
||||||
@@ -447,7 +447,7 @@ fn todo_summary(todos: &[TodoRecord]) -> String {
|
|||||||
|
|
||||||
fn render_page_swap(title: &'static str, message: &'static str) -> Html {
|
fn render_page_swap(title: &'static str, message: &'static str) -> Html {
|
||||||
// req: html_safety/002 req: view/001 req: component/003
|
// req: html_safety/002 req: view/001 req: component/003
|
||||||
page_swap::render(&PageSwap {
|
page_swap::page(&PageSwap {
|
||||||
content: render_docs_content(message),
|
content: render_docs_content(message),
|
||||||
title,
|
title,
|
||||||
})
|
})
|
||||||
@@ -455,7 +455,7 @@ fn render_page_swap(title: &'static str, message: &'static str) -> Html {
|
|||||||
|
|
||||||
fn render_docs_content(message: &'static str) -> Html {
|
fn render_docs_content(message: &'static str) -> Html {
|
||||||
// req: html_safety/002 req: view/001 req: component/003
|
// req: html_safety/002 req: view/001 req: component/003
|
||||||
hemx::page(&DocsContent { message })
|
ui::page(&DocsContent { message })
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@@ -570,7 +570,7 @@ mod tests {
|
|||||||
title: "<b>Ship v0</b>".to_owned(),
|
title: "<b>Ship v0</b>".to_owned(),
|
||||||
}];
|
}];
|
||||||
|
|
||||||
let html = hemx::page(&todos_view(&todos));
|
let html = ui::page(&todos_view(&todos));
|
||||||
let document = Html::parse_fragment(html.as_str());
|
let document = Html::parse_fragment(html.as_str());
|
||||||
let rows = document
|
let rows = document
|
||||||
.select(&selector(&keyed_items_selector("li")))
|
.select(&selector(&keyed_items_selector("li")))
|
||||||
@@ -590,7 +590,7 @@ mod tests {
|
|||||||
// req: html_safety/002 req: view/001 req: test/005
|
// req: html_safety/002 req: view/001 req: test/005
|
||||||
#[test]
|
#[test]
|
||||||
fn empty_todos_payload_is_rendered_by_a_hemplate_view() {
|
fn empty_todos_payload_is_rendered_by_a_hemplate_view() {
|
||||||
let html = hemx::page(&todos_view(&[]));
|
let html = ui::page(&todos_view(&[]));
|
||||||
let document = Html::parse_fragment(html.as_str());
|
let document = Html::parse_fragment(html.as_str());
|
||||||
let rows = document
|
let rows = document
|
||||||
.select(&selector(&list_item_selector("")))
|
.select(&selector(&list_item_selector("")))
|
||||||
|
|||||||
+10
-6
@@ -732,6 +732,7 @@ 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}#[doc(hidden)]\n"));
|
||||||
out.push_str(&format!(
|
out.push_str(&format!(
|
||||||
"{pad}pub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html {{\n"
|
"{pad}pub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html {{\n"
|
||||||
));
|
));
|
||||||
@@ -1733,9 +1734,9 @@ mod tests {
|
|||||||
));
|
));
|
||||||
assert!(generated.contains("#[doc(hidden)]\npub fn lower_html"));
|
assert!(generated.contains("#[doc(hidden)]\npub fn lower_html"));
|
||||||
assert!(generated.contains("pub fn static_fragment(html: &'static str) -> ::hemx::Html"));
|
assert!(generated.contains("pub fn static_fragment(html: &'static str) -> ::hemx::Html"));
|
||||||
assert!(
|
assert!(generated.contains(
|
||||||
generated.contains("pub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
"#[doc(hidden)]\npub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"
|
||||||
);
|
));
|
||||||
assert!(generated.contains("pub fn page(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"
|
||||||
@@ -1846,9 +1847,9 @@ mod tests {
|
|||||||
));
|
));
|
||||||
assert!(generated.contains("\n#[doc(hidden)]\npub fn lower_html"));
|
assert!(generated.contains("\n#[doc(hidden)]\npub fn lower_html"));
|
||||||
assert!(generated.contains("\npub fn static_fragment(html: &'static str) -> ::hemx::Html"));
|
assert!(generated.contains("\npub fn static_fragment(html: &'static str) -> ::hemx::Html"));
|
||||||
assert!(
|
assert!(generated.contains(
|
||||||
generated.contains("\npub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
"\n#[doc(hidden)]\npub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"
|
||||||
);
|
));
|
||||||
assert!(
|
assert!(
|
||||||
generated.contains("\npub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
generated.contains("\npub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
||||||
);
|
);
|
||||||
@@ -1865,6 +1866,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(
|
||||||
|
" #[doc(hidden)]\n pub fn render(view: &impl ::hemplate::Hemplate) -> ::hemx::Html"
|
||||||
|
));
|
||||||
assert!(
|
assert!(
|
||||||
generated.contains(" pub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
generated.contains(" pub fn page(view: &impl ::hemplate::Hemplate) -> ::hemx::Html")
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1165,6 +1165,12 @@ impl<T> core::fmt::Display for Form<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> GeneratedTarget for Form<T> {
|
||||||
|
fn __hemx_resource_id(self) -> ResourceId {
|
||||||
|
self.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Form<T> {
|
impl<T> Form<T> {
|
||||||
pub const fn new(id: u32) -> Self {
|
pub const fn new(id: u32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
Reference in New Issue
Block a user