fix(examples): use lower-aware slot html updates

Move canonical examples and docs off direct RenderSlotExt render shortcuts so slot updates use generated render/lowering before HTML replacement, preserving runtime metadata for follow-up interactions.

req: component/003

req: runtime/001

req: dx/006

req: examples/003
This commit is contained in:
slhx agent
2026-06-02 01:48:10 +02:00
parent e0c4633d25
commit 732e65008e
6 changed files with 10 additions and 9 deletions
+1 -1
View File
@@ -76,7 +76,7 @@ slhx competes with React by making frontend frameworks unnecessary for most apps
005 Error messages must explain fixes in author language, not internal language. Say “add `h-key="todo.id"` to this `h-for`”, not “missing ScopeKey for ResourceRef”. 005 Error messages must explain fixes in author language, not internal language. Say “add `h-key="todo.id"` to this `h-for`”, not “missing ScopeKey for ResourceRef”.
### req: dx/006 ### req: dx/006
006 Generated resource methods are the preferred authoring API: `slots::todo_list.render(view)`, `slots::card.replace(key, view)`, `slots::count.text(42)`, `atoms::user.set(user)`. The public facade and generated view modules expose `render(view)` for trusted hemplate-to-`SafeHtml` page and fragment composition, `static_fragment(include_str!(...))` for prototype/static `.heml` fragments that need generated resource lowering as `SafeHtml`, plus `lower(html)` for callers that need the lowered string; `render_html(view)` and `lower_html(html)` remain explicit compatibility aliases. These return `impl IntoEffect`, `SafeHtml`, or lowered HTML at the boundary. Raw `Effect` constructors, opcodes, and `EffectWriter` remain low-level. [north_star] 006 Generated resource methods are the preferred authoring API: `slots::todo_list.html(ui::render(&view))`, `slots::card.replace(key, view)`, `slots::count.text(42)`, `atoms::user.set(user)`. The public facade and generated view modules expose `render(view)` for trusted hemplate-to-`SafeHtml` page and fragment composition, `static_fragment(include_str!(...))` for prototype/static `.heml` fragments that need generated resource lowering as `SafeHtml`, plus `lower(html)` for callers that need the lowered string; `render_html(view)` and `lower_html(html)` remain explicit compatibility aliases. These return `impl IntoEffect`, `SafeHtml`, or lowered HTML at the boundary. Raw `Effect` constructors, opcodes, and `EffectWriter` remain low-level. [north_star]
### req: dx/007 ### req: dx/007
007 Tuple composition of `IntoEffect` is the canonical batch syntax: `(a, b, c)` implements `IntoEffect` up to arity 12. `Effect::batch((...))` is available but not required for the happy path. 007 Tuple composition of `IntoEffect` is the canonical batch syntax: `(a, b, c)` implements `IntoEffect` up to arity 12. `Effect::batch((...))` is available but not required for the happy path.
+1 -1
View File
@@ -240,7 +240,7 @@ pub fn apply_board_patch(
PatchResult::Conflict { canonical_board } => Effect::batch(( PatchResult::Conflict { canonical_board } => Effect::batch((
Effect::set(atoms::BOARD, canonical_board.clone()), Effect::set(atoms::BOARD, canonical_board.clone()),
slots::board.render(&BoardView::from(canonical_board)), slots::board.html(ui::render(&BoardView::from(canonical_board))),
)), )),
} }
} }
+2 -2
View File
@@ -6,7 +6,7 @@ mod tests {
use super::ui::{board, board_card}; use super::ui::{board, board_card};
use hemplate::Hemplate; use hemplate::Hemplate;
use scraper::{Html, Selector}; use scraper::{Html, Selector};
use slhx::{Effect, IntoEffect, Payload, RenderSlotExt}; use slhx::{Effect, IntoEffect, Payload};
use slhx_test::inspect; use slhx_test::inspect;
#[derive(Hemplate)] #[derive(Hemplate)]
@@ -27,7 +27,7 @@ mod tests {
#[test] #[test]
fn kanban_board_updates_generated_slot() { fn kanban_board_updates_generated_slot() {
fn render_board() -> impl IntoEffect { fn render_board() -> impl IntoEffect {
board::slots::board.render(&empty_board()) board::slots::board.html(slhx::render(&empty_board()))
} }
let effect = inspect(render_board()); let effect = inspect(render_board());
+2 -2
View File
@@ -7,7 +7,7 @@ mod tests {
use super::ui::issue_card::handles as card_handles; use super::ui::issue_card::handles as card_handles;
use super::ui::issue_lane::events as lane_events; use super::ui::issue_lane::events as lane_events;
use hemplate::Hemplate; use hemplate::Hemplate;
use slhx::{Effect, IntoEffect, Payload, RenderSlotExt}; use slhx::{Effect, IntoEffect, Payload};
use slhx_test::inspect; use slhx_test::inspect;
#[derive(Hemplate)] #[derive(Hemplate)]
@@ -30,7 +30,7 @@ mod tests {
fn techdemo_uses_generated_slots_for_multi_target_updates() { fn techdemo_uses_generated_slots_for_multi_target_updates() {
fn update() -> impl IntoEffect { fn update() -> impl IntoEffect {
( (
slots::hero_metrics.render(&FastMetric { label: "fast" }), slots::hero_metrics.html(slhx::render(&FastMetric { label: "fast" })),
slots::notice.text("typed"), slots::notice.text("typed"),
) )
} }
+3 -3
View File
@@ -5,7 +5,7 @@ pub mod ui {}
mod tests { mod tests {
use super::ui::{auth, counter, notifications, page_swap, todos, wizard}; use super::ui::{auth, counter, notifications, page_swap, todos, wizard};
use hemplate::Hemplate; use hemplate::Hemplate;
use slhx::{push, Effect, IntoEffect, NavigateMode, Payload, RenderKeyedSlotExt, RenderSlotExt}; use slhx::{push, Effect, IntoEffect, NavigateMode, Payload, RenderKeyedSlotExt};
use slhx_test::inspect; use slhx_test::inspect;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@@ -121,9 +121,9 @@ mod tests {
fn page_swap_updates_content_and_history() { fn page_swap_updates_content_and_history() {
fn load_docs() -> impl IntoEffect { fn load_docs() -> impl IntoEffect {
( (
page_swap::slots::content.render(&DocsContent { page_swap::slots::content.html(slhx::render(&DocsContent {
message: "This page was swapped.", message: "This page was swapped.",
}), })),
page_swap::slots::title.text("Docs"), page_swap::slots::title.text("Docs"),
push("/docs"), push("/docs"),
) )
+1
View File
@@ -116,6 +116,7 @@ fn canonical_example_docs_do_not_teach_low_level_plumbing() {
"lower_html(", "lower_html(",
"render_html(", "render_html(",
"SafeHtml::trusted", "SafeHtml::trusted",
".render(&",
]; ];
let mut failures = Vec::new(); let mut failures = Vec::new();
scan_examples(&examples, &mut |path, text| { scan_examples(&examples, &mut |path, text| {