inertia-rust 2.4.6

A Rust server-adapter for building modern MVC web apps with Inertia.
Documentation
use async_trait::async_trait;
use inertia_rust::{template_resolvers::TemplateResolver, InertiaError, ViewData};
use std::path::Path;

use crate::super_trim;

pub fn get_dynamic_csr_expect(url: &str, props: &str, component: &str, version: &str) -> String {
    super_trim(format!(
        r#"
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="ssr" value="false">
    <title inertia></title>
    
</head>
<body>
    <div id="app" data-page={{"component":"{}","props":{},"url":"{}","version":"{}","clearHistory":false,"encryptHistory":false}}></div>
</body>
</html>"#,
        component, props, url, version
    ))
}

pub fn get_dynamic_csr_with_view_data_expect(
    url: &str,
    props: &str,
    component: &str,
    version: &str,
    title: &str,
    is_ssr: bool,
) -> String {
    super_trim(format!(
        r#"
<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <meta name="ssr" value="{}">
    <title inertia>{}</title>
    
</head>
<body>
    <div id="app" data-page={{"component":"{}","props":{},"url":"{}","version":"{}","clearHistory":false,"encryptHistory":false}}></div>
</body>
</html>"#,
        is_ssr, title, component, props, url, version
    ))
}

pub struct MockedTemplateResolver {
    root_template: String,
}

impl MockedTemplateResolver {
    pub fn new(template_path: &str) -> Result<Self, InertiaError> {
        let path = Path::new(template_path);

        let file_data = std::fs::read(path).map_err(|err| {
            InertiaError::RenderError(format!(
                "Failed to open root layout at {}: {:#}",
                path.to_str().unwrap(),
                err
            ))
        })?;

        let root_template = String::from_utf8(file_data).map_err(|err| {
            InertiaError::RenderError(format!("Failed to read file contents: {err:?}"))
        })?;

        Ok(Self { root_template })
    }
}

#[async_trait(?Send)]
impl TemplateResolver for MockedTemplateResolver {
    async fn resolve_template(&self, view_data: ViewData<'_>) -> Result<String, InertiaError> {
        let mut html = self.root_template.clone();

        html = html.replace(
            "%-view_data_title-%",
            view_data
                .custom_props
                .get("title")
                .map(|v| v.as_str().unwrap())
                .unwrap_or(""),
        );

        html = html.replace(
            "%-view_data_ssr-%",
            &view_data
                .custom_props
                .get("isSsr")
                .map(|v| v.as_bool().unwrap())
                .unwrap_or_default()
                .to_string(),
        );

        match view_data.ssr_page {
            Some(ssr) => {
                html = html.replace("%-inertia_body-%", &ssr.get_body());
                html = html.replace("%-inertia_head-%", &ssr.get_head());
            }
            None => {
                let stringified_page: Result<String, serde_json::Error> =
                    serde_json::to_string(&view_data.page);

                if stringified_page.is_err() {
                    return Err(InertiaError::SerializationError(format!(
                        "Failed to serialize view_data.page: {:?}",
                        &view_data.page
                    )));
                }

                let stringified_page = stringified_page.unwrap();

                let container = format!("<div id=\"app\" data-page={stringified_page}></div>",);
                html = html.replace("%-inertia_body-%", &container);
                html = html.replace("%-inertia_head-%", "");
            }
        }

        Ok(html)
    }
}