use crate::app::AppConfig; use crate::website::page::{Page, PageTemplate}; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::path::PathBuf; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct WebSite { root_page: Page, #[serde(default = "AssetsIndex::new")] assets_index: AssetsIndex, templates: Vec<PageTemplate>, #[serde(default = "HashMap::new")] pages_index: HashMap<PathBuf, Page>, } #[derive(Debug, Serialize, Deserialize, Clone)] pub struct AssetsIndex { pub images: Vec<String>, pub sounds: Vec<String>, pub videos: Vec<String>, pub docs: Vec<String>, pub source_code: Vec<String>, } impl AssetsIndex { pub fn new() -> Self { AssetsIndex { images: Vec::new(), sounds: Vec::new(), videos: Vec::new(), docs: Vec::new(), source_code: Vec::new(), } } } impl WebSite { pub fn from_json(json: &str) -> Self { let mut obj: WebSite = serde_json::from_str(json).unwrap(); obj.root_page.build_with_template( obj.templates .iter() .find(|t| t.name == obj.root_page.template_name) .expect("Page template not found") .clone(), ); obj.root_page.build_html(); for p in obj.root_page.sub_pages.iter_mut() { p.build_with_template( obj.templates .iter() .find(|t| t.name == p.template_name) .expect("Page template not found") .clone(), ); p.build_html(); } obj.build_assets_index(); obj.build_pages_index(obj.root_page.clone(), PathBuf::from("/")); obj } pub fn load(config: &AppConfig) -> WebSite { let file_path = match &config.load { None => std::env::current_dir() .unwrap() .join("templates") .join("new_website.json"), Some(pth) => pth.clone(), }; WebSite::from_json(&std::fs::read_to_string(file_path).unwrap()) } 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()); } } fn build_assets_index(&mut self) { return; } 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 = WebSite::from_json(TEST_JSON_WEBSITE); 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"); } }