Skip to main content

coil_runtime/render/
mod.rs

1use super::*;
2use coil_i18n::I18nError;
3use coil_seo::SeoError;
4use coil_template::{DocumentRenderRequest, TemplateKind, TemplateModelError};
5use thiserror::Error;
6
7mod model;
8mod seo;
9mod templates;
10
11#[derive(Debug, Error)]
12pub enum RuntimeRenderError {
13    #[error(transparent)]
14    Template(#[from] TemplateModelError),
15    #[error(transparent)]
16    I18n(#[from] I18nError),
17    #[error(transparent)]
18    Seo(#[from] SeoError),
19    #[error(transparent)]
20    RouteUrl(#[from] RouteUrlError),
21}
22
23impl RuntimePlan {
24    pub fn render_page_response(
25        &self,
26        execution: &RequestExecution,
27        page: &PageResponse,
28        extra_metadata: Option<&TypedMetadata>,
29    ) -> Result<String, RuntimeRenderError> {
30        let selector = templates::template_selector(&page.template)?;
31        let namespaces = self.template_namespaces_for_execution(execution);
32        let model = self.render_model_for_execution(execution, &page.template, None)?;
33
34        let html = match self.template.runtime.render_document(
35            &namespaces,
36            DocumentRenderRequest::new(selector.clone(), model.clone()),
37        ) {
38            Ok(output) => output.html,
39            Err(TemplateModelError::TemplateNotFound { .. })
40            | Err(TemplateModelError::TemplateKindMismatch {
41                actual: TemplateKind::Fragment,
42                ..
43            }) => {
44                let content =
45                    self.render_fragment_content(execution, &namespaces, &selector, model, None)?;
46                self.render_document_shell(execution, &page.template, content)?
47            }
48            Err(error) => return Err(error.into()),
49        };
50
51        self.decorate_page_document(execution, &page.template, html, extra_metadata)
52    }
53
54    pub fn render_fragment_response(
55        &self,
56        execution: &RequestExecution,
57        fragment: &FragmentResponse,
58    ) -> Result<String, RuntimeRenderError> {
59        let selector = templates::template_selector(&fragment.template)?;
60        let namespaces = self.template_namespaces_for_execution(execution);
61        let model = self.render_model_for_execution(
62            execution,
63            &fragment.template,
64            Some(fragment.fragment_id.as_str()),
65        )?;
66
67        self.render_fragment_content(
68            execution,
69            &namespaces,
70            &selector,
71            model,
72            Some(fragment.fragment_id.as_str()),
73        )
74        .map_err(Into::into)
75    }
76}