77 lines
2.1 KiB
Rust
77 lines
2.1 KiB
Rust
use std::path::Path;
|
|
use std::process::exit;
|
|
use std::sync::Arc;
|
|
|
|
use axum::response::{Html, IntoResponse};
|
|
use serde::Serialize;
|
|
use tera::{Tera, Context};
|
|
|
|
use crate::{errors::Error, localization::Localization};
|
|
|
|
|
|
#[derive(Clone)]
|
|
pub struct TemplateEngine {
|
|
pub tera: Arc<Tera>,
|
|
}
|
|
|
|
#[derive(Debug)]
|
|
pub enum TemplateError {
|
|
SerializationError { reason: Box<dyn std::error::Error> },
|
|
RenderError { name: String, reason: Box<dyn std::error::Error> },
|
|
}
|
|
|
|
impl TemplateEngine {
|
|
pub fn new(template_directory: &Path, localization: Localization) -> Self {
|
|
let template_glob = template_directory.join("**").join("*");
|
|
match Tera::new(template_glob.to_str().expect("valid glob path string")) {
|
|
Ok(mut tera) => {
|
|
tera.register_function("tr", localization);
|
|
TemplateEngine { tera: Arc::new(tera) }
|
|
},
|
|
Err(e) => {
|
|
println!("Loading templates failed: {}", e);
|
|
exit(1)
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
}
|
|
}
|
|
|
|
pub struct Template<'n, S: Serialize> {
|
|
pub name: &'n str,
|
|
pub engine: TemplateEngine,
|
|
pub context: S,
|
|
}
|
|
|
|
impl<'n, S: Serialize> Template<'n, S> {
|
|
pub fn new(name: &'n str, engine: TemplateEngine, context: S) -> Self {
|
|
Template {
|
|
name,
|
|
engine,
|
|
context,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<S: Serialize> IntoResponse for Template<'_, S> {
|
|
fn into_response(self) -> axum::response::Response {
|
|
let res = self.engine.render(self.name, self.context);
|
|
|
|
match res {
|
|
Ok(content) => Html(content).into_response(),
|
|
Err(err) => Error::from(err).into_response(),
|
|
}
|
|
}
|
|
}
|