use actix_web::HttpResponse;
use regex::Regex;
use std::fmt::Display;
use yew::html::BaseComponent;
use yew::ServerRenderer;
pub fn app_path(src: impl Into<String>) -> String {
let src: String = src.into();
if let Some(tail) = src.strip_prefix("/") {
let root = crate::app_root();
return format!("{root}{tail}");
}
src
}
pub fn app_path2(src: impl Into<String>, tail: impl Display) -> String {
let src = app_path(src);
format!("{src}/{tail}")
}
pub async fn render<V, VM, E>(args: VM) -> Result<HttpResponse, E>
where
V: BaseComponent,
V: BaseComponent<Properties = VM>,
VM: Send + 'static,
{
let renderer = ServerRenderer::<V>::with_props(|| args);
let html = renderer.render().await;
let html = format!("<!DOCTYPE html>\n{html}");
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(html))
}
pub async fn render_min<V, VM, E>(args: VM) -> Result<HttpResponse, E>
where
V: BaseComponent,
V: BaseComponent<Properties = VM>,
VM: Send + 'static,
{
let renderer = ServerRenderer::<V>::with_props(|| args);
let html = renderer.render().await;
let html = strip_html_comments(&html);
let html = format!("<!DOCTYPE html>\n{html}");
Ok(HttpResponse::Ok()
.content_type("text/html; charset=utf-8")
.body(html))
}
pub async fn render_turbo_stream<V, VM, E>(args: VM) -> Result<HttpResponse, E>
where
V: BaseComponent,
V: BaseComponent<Properties = VM>,
VM: Send + 'static,
{
let renderer = ServerRenderer::<V>::with_props(|| args);
let html = renderer.render().await;
let html = strip_html_comments(&html);
Ok(HttpResponse::Ok()
.content_type("text/vnd.turbo-stream.html")
.body(html))
}
pub async fn render_turbo_stream_full<V, VM, E>(args: VM) -> Result<HttpResponse, E>
where
V: BaseComponent,
V: BaseComponent<Properties = VM>,
VM: Send + 'static,
{
let renderer = ServerRenderer::<V>::with_props(|| args);
let html = renderer.render().await;
Ok(HttpResponse::Ok()
.content_type("text/vnd.turbo-stream.html")
.body(html))
}
pub fn redirect<E>(path: impl Into<String>) -> Result<HttpResponse, E> {
let path: String = app_path(path);
Ok(HttpResponse::SeeOther()
.insert_header(("Location", path))
.finish())
}
fn strip_html_comments(input: &str) -> String {
let re = Regex::new(r"(?s)<!--.*?-->").unwrap();
re.replace_all(input, "").into_owned()
}