lssg_lib/renderer/
renderer.rs1use std::cell::{RefCell, UnsafeCell};
2use std::rc::Rc;
3
4use log::{debug, error, info, warn};
5
6use crate::sitetree::Input;
7use crate::{
8 html::DomTree,
9 sitetree::{SiteNodeKind, SiteTree},
10 LssgError,
11};
12
13use super::{modules::RendererModule, DefaultModule};
14use super::{RenderContext, TokenRenderer};
15
16pub struct Renderer {
19 modules: Vec<Box<dyn RendererModule>>,
20}
21
22impl Renderer {
23 pub fn new() -> Renderer {
24 Renderer { modules: vec![] }
25 }
26
27 pub fn add_module(&mut self, module: impl RendererModule + 'static) {
28 self.modules.push(Box::new(module));
29 }
30
31 pub fn init(&mut self, site_tree: &mut SiteTree) {
33 debug!("running init");
34 let failed: Vec<usize> = self
35 .modules
36 .iter_mut()
37 .enumerate()
38 .filter_map(|(i, module)| match module.init(site_tree) {
39 Ok(_) => None,
40 Err(e) => {
41 error!("Failed to do site_init on {}: {e}", module.id());
42 Some(i)
43 }
44 })
45 .collect();
46 for i in failed.into_iter().rev() {
47 self.modules.remove(i);
48 }
49 }
50
51 pub fn after_init(&mut self, site_tree: &SiteTree) {
53 debug!("running after_init");
54 let failed: Vec<usize> = self
55 .modules
56 .iter_mut()
57 .enumerate()
58 .filter_map(|(i, module)| match module.after_init(site_tree) {
59 Ok(_) => None,
60 Err(e) => {
61 error!("Failed to do site_init on {}: {e}", module.id());
62 Some(i)
63 }
64 })
65 .collect();
66 for i in failed.into_iter().rev() {
67 self.modules.remove(i);
68 }
69 }
70
71 pub fn render(&mut self, site_tree: &SiteTree, site_id: usize) -> Result<String, LssgError> {
73 let site_node = site_tree.get(site_id)?;
75 let page = match &site_node.kind {
76 SiteNodeKind::Page(page) => page,
77 _ => return Err(LssgError::render("Invalid node type given")),
78 };
79
80 let mut dom = DomTree::new();
81
82 let context = RenderContext {
83 input: site_tree.get_input(site_id),
84 site_tree,
85 site_id,
86 page,
87 };
88
89 for module in &mut self.modules {
91 debug!("running render_page on {}", module.id());
92 module.render_page(&mut dom, &context);
93 }
94
95 debug!("running render_body on modules");
96 let tr = TokenRenderer::new(&mut self.modules);
97 tr.start_render(&mut dom, &context);
98
99 for module in &mut self.modules {
100 debug!("running after_render on {}", module.id());
101 module.after_render(&mut dom, &context);
102 }
103
104 dom.validate();
106
107 return Ok(dom.to_html_string());
112 }
113}