1use crate::{engine::TemplateEngine, response::ViewResponse};
2use doido_core::Result;
3use std::sync::Arc;
4
5pub struct Renderer {
6 engine: Arc<dyn TemplateEngine>,
7 default_layout: String,
8}
9
10impl Renderer {
11 pub fn new(engine: Arc<dyn TemplateEngine>, default_layout: impl Into<String>) -> Self {
12 Self {
13 engine,
14 default_layout: default_layout.into(),
15 }
16 }
17
18 pub fn render(&self, response: &ViewResponse) -> Result<String> {
19 let content = self.engine.render(&response.template, &response.context)?;
20
21 let layout = match &response.layout {
22 Some(l) if l.is_empty() => return Ok(content),
23 Some(l) => l.clone(),
24 None => self.default_layout.clone(),
25 };
26
27 if layout.is_empty() {
28 return Ok(content);
29 }
30
31 let mut layout_ctx = response.context.clone();
32 if let Some(obj) = layout_ctx.as_object_mut() {
33 obj.insert(
34 "content_for_layout".to_string(),
35 serde_json::Value::String(content),
36 );
37 }
38 self.engine
39 .render(&format!("layouts/{}", layout), &layout_ctx)
40 }
41}