nomilo/src/template.rs

74 lines
1.9 KiB
Rust
Raw Normal View History

2022-04-29 02:29:10 +00:00
use std::path::Path;
use std::process::exit;
2024-12-22 21:36:26 +00:00
use std::sync::Arc;
2022-04-29 02:29:10 +00:00
2024-12-22 21:36:26 +00:00
use axum::response::{Html, IntoResponse};
2022-04-29 02:29:10 +00:00
use serde::Serialize;
use tera::{Tera, Context};
2024-12-22 21:36:26 +00:00
use crate::errors::Error;
2022-04-29 02:29:10 +00:00
2024-12-22 21:36:26 +00:00
#[derive(Clone)]
pub struct TemplateEngine {
tera: Arc<Tera>,
2022-04-29 02:29:10 +00:00
}
2024-12-22 21:36:26 +00:00
pub enum TemplateError {
SerializationError { reason: Box<dyn std::error::Error> },
RenderError { name: String, reason: Box<dyn std::error::Error> },
}
impl TemplateEngine {
2022-04-29 02:33:00 +00:00
pub fn new(template_directory: &Path) -> Self {
let template_glob = template_directory.join("**").join("*");
match Tera::new(template_glob.to_str().expect("valid glob path string")) {
2024-12-22 21:36:26 +00:00
Ok(tera) => TemplateEngine { tera: Arc::new(tera) },
2022-04-29 02:33:00 +00:00
Err(e) => {
println!("Loading templates failed: {}", e);
exit(1)
}
}
}
2024-12-22 21:36:26 +00:00
pub fn render<S: Serialize>(&self, name: &str, context: S) -> Result<String, TemplateError> {
let context = Context::from_serialize(context).map_err(|e| {
TemplateError::SerializationError { reason: Box::new(e) }
})?;
let content = self.tera.render(name, &context).map_err(|e| {
TemplateError::RenderError { name: name.into(), reason: Box::new(e) }
})?;
Ok(content)
}
2022-04-29 02:29:10 +00:00
}
2024-12-22 21:36:26 +00:00
pub struct Template<'n, S: Serialize> {
pub name: &'n str,
pub engine: TemplateEngine,
2022-04-29 02:33:00 +00:00
pub context: S,
2022-04-29 02:29:10 +00:00
}
2024-12-22 21:36:26 +00:00
impl<'n, S: Serialize> Template<'n, S> {
pub fn new(name: &'n str, engine: TemplateEngine, context: S) -> Self {
2022-04-29 02:33:00 +00:00
Template {
name,
2024-12-22 21:36:26 +00:00
engine,
context,
2022-04-29 02:33:00 +00:00
}
}
2022-04-29 02:29:10 +00:00
}
2024-12-22 21:36:26 +00:00
impl<S: Serialize> IntoResponse for Template<'_, S> {
fn into_response(self) -> axum::response::Response {
let res = self.engine.render(self.name, self.context);
2022-04-29 02:29:10 +00:00
2024-12-22 21:36:26 +00:00
match res {
Ok(content) => Html(content).into_response(),
Err(err) => Error::from(err).into_response(),
}
2022-04-29 02:29:10 +00:00
}
}