0ede5eb113
Keep the beginner prelude on generated lower-aware render/html paths instead of exposing RenderSlotExt, which can bypass generated runtime metadata. req: dx/006 req: component/003 req: runtime/001
119 lines
3.3 KiB
Rust
119 lines
3.3 KiB
Rust
//! 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<T> RenderSlotExt for Slot<T> {
|
|
fn render(self, view: &impl hemplate::Hemplate) -> Effect {
|
|
self.html(render(view))
|
|
}
|
|
}
|
|
|
|
pub trait RenderKeyedSlotExt<K> {
|
|
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<K, T> RenderKeyedSlotExt<K> for KeyedSlot<K, T>
|
|
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("<strong>ok</strong>");
|
|
Ok(())
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn render_is_the_short_safe_html_helper() {
|
|
// req: dx/006 req: html_safety/002
|
|
assert_eq!(crate::render(&InlineView).as_str(), "<strong>ok</strong>");
|
|
assert_eq!(crate::render_html(&InlineView).as_str(), "<strong>ok</strong>");
|
|
}
|
|
|
|
#[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(), "<strong>ok</strong>");
|
|
}
|
|
}
|