use super::page::{Page, PageTemplate}; use crate::app::AppConfig; use crate::static_files::StaticFilesManager; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct WebSiteBuilder { root_page: Page, #[serde(default = "Vec::new")] assets_index: Vec<String>, templates: Vec<PageTemplate>, } #[derive(Debug, Clone)] pub struct WebSite { root_page: Page, pub static_files_manager: StaticFilesManager, templates: Vec<PageTemplate>, pages_index: HashMap<PathBuf, Page>, } impl WebSiteBuilder { pub fn from_json(json: &str) -> Self { serde_json::from_str(json).unwrap() } pub fn with_static_files_manager( &mut self, static_files_manager: StaticFilesManager, ) -> WebSite { WebSite { root_page: self.root_page.clone(), static_files_manager: { let mut static_files_manager = static_files_manager; static_files_manager.add_pathes(&self.assets_index); static_files_manager }, templates: self.templates.clone(), pages_index: HashMap::new(), } } pub fn load(config: &AppConfig) -> WebSiteBuilder { let file_path = match &config.load { None => std::env::current_dir() .unwrap() .join("templates") .join("new_website.json"), Some(pth) => pth.clone(), }; WebSiteBuilder::from_json(&std::fs::read_to_string(file_path).unwrap()) } } impl WebSite { pub fn build(&mut self) -> Self { self.root_page.build_with_template( self.templates .iter() .find(|t| t.name == self.root_page.template_name) .expect("Page template not found") .clone(), ); self.root_page.build_html(); for p in self.root_page.sub_pages.iter_mut() { p.build_with_template( self.templates .iter() .find(|t| t.name == p.template_name) .expect("Page template not found") .clone(), ); p.build_html(); } self.build_pages_index(self.root_page.clone(), PathBuf::from("/")); self.clone() } fn build_pages_index(&mut self, root_page: Page, from_url: PathBuf) { let url = from_url.join(&root_page.metadata.url_slug); self.pages_index.insert(url.clone(), root_page.clone()); for p in root_page.sub_pages { self.build_pages_index(p, url.clone()); } } pub fn get_page_by_url(&self, url: &PathBuf) -> Option<&Page> { self.pages_index.get(&PathBuf::from("/").join(url)) } } #[cfg(test)] mod test_website { use super::*; use crate::testing::TEST_JSON_WEBSITE; #[test] fn test_index_pages_by_slug() { let website = WebSiteBuilder::from_json(TEST_JSON_WEBSITE) .with_static_files_manager(StaticFilesManager { dir: PathBuf::from("."), index: Vec::new(), }) .build(); let root_page = website.get_page_by_url(&PathBuf::from("/")); assert!(root_page.is_some()); assert_eq!(root_page.unwrap().metadata.title, "TEST"); let sub_page = website.get_page_by_url(&PathBuf::from("subpage")); assert!(sub_page.is_some()); assert_eq!(sub_page.unwrap().metadata.title, "TEST SUBPAGE"); let nested_page = website.get_page_by_url(&PathBuf::from("subpage/nested")); assert!(nested_page.is_some()); assert_eq!(nested_page.unwrap().metadata.title, "TEST NESTED"); } }