//! Public authoring facade for slhx applications. //! //! Most application code should depend on this crate, use the proc-macros from //! here, and import generated resources through `#[slhx::surface]`. pub use slhx_core::*; pub use slhx_derive::{app, component, form, handler, surface}; pub fn render(view: &impl hemplate::Hemplate) -> SafeHtml { let mut html = String::new(); view.render_into(&mut html) .expect("hemplate view renders into slhx effect payload"); SafeHtml::trusted(html) } pub fn render_html(view: &impl hemplate::Hemplate) -> SafeHtml { render(view) } pub trait RenderSlotExt { fn render(self, view: &impl hemplate::Hemplate) -> Effect; fn render_view(self, view: &impl hemplate::Hemplate) -> Effect where Self: Sized, { self.render(view) } } impl RenderSlotExt for Slot { fn render(self, view: &impl hemplate::Hemplate) -> Effect { self.html(render(view)) } } pub trait RenderKeyedSlotExt { fn append(self, key: K, view: &impl hemplate::Hemplate) -> Effect; fn prepend(self, key: K, view: &impl hemplate::Hemplate) -> Effect; fn replace(self, key: K, view: &impl hemplate::Hemplate) -> Effect; fn append_view(self, key: K, view: &impl hemplate::Hemplate) -> Effect where Self: Sized, { self.append(key, view) } fn prepend_view(self, key: K, view: &impl hemplate::Hemplate) -> Effect where Self: Sized, { self.prepend(key, view) } fn replace_view(self, key: K, view: &impl hemplate::Hemplate) -> Effect where Self: Sized, { self.replace(key, view) } } impl RenderKeyedSlotExt for KeyedSlot where K: ToString, { fn append(self, key: K, view: &impl hemplate::Hemplate) -> Effect { self.append_html(key, render(view)) } fn prepend(self, key: K, view: &impl hemplate::Hemplate) -> Effect { self.prepend_html(key, render(view)) } fn replace(self, key: K, view: &impl hemplate::Hemplate) -> Effect { self.replace_html(key, render(view)) } } pub mod prelude { pub use slhx_core::{ navigate, push, redirect, replace, Atom, BuildFingerprint, ComponentRef, CssClass, CssClasses, Effect, EventName, Form, FormModel, FormValue, Handle, IntoEffect, KeyedSlot, ParamName, SafeHtml, Slot, }; pub use crate::{render, render_html, RenderKeyedSlotExt}; pub use slhx_derive::{app, component, form, handler, surface}; } #[cfg(test)] mod tests { struct InlineView; impl hemplate::Hemplate for InlineView { fn render_into(&self, out: &mut String) -> Result<(), hemplate::error::HemplateError> { out.push_str("ok"); Ok(()) } } #[test] fn render_is_the_short_safe_html_helper() { // req: dx/006 req: html_safety/002 assert_eq!(crate::render(&InlineView).as_str(), "ok"); assert_eq!(crate::render_html(&InlineView).as_str(), "ok"); } #[test] fn prelude_exports_safe_html_for_page_composition() { // req: dx/006 req: html_safety/002 use crate::prelude::*; let html = SafeHtml::join([render(&InlineView)]); assert_eq!(html.as_str(), "ok"); } }