Newer
Older
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PageData {
pub title: String,
pub lang: String,
pub description: String,
pub slug: String,
pub html_body: String,
pub css_src: Option<String>,
pub js_src: Option<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct HtmlDoc(String);
impl HtmlDoc {
fn load_template() -> String {
std::fs::read_to_string(
std::env::current_dir()
.unwrap()
.join("templates")
.join("html_doc.html"),
)
pub fn from_page_data(page_data: &PageData) -> Self {
let html = re
.replace_all(&HtmlDoc::load_template(), |captures: &Captures| {
let placeholder = captures.iter().next().unwrap().unwrap().as_str();
let placeholder = placeholder[1..placeholder.len() - 1].to_owned();
page_data.field_from_str_key(placeholder)
})
.to_string();
}
pub fn to_string(&self) -> String {
self.0.clone()
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebPage {
pub page_data: PageData,
}
impl PageData {
pub fn to_web_page(&self) -> WebPage {
WebPage {
page_data: self.clone(),
html_doc: HtmlDoc::from_page_data(&self),
}
}
pub fn field_from_str_key(&self, key: String) -> String {
match &key[..] {
"title" => self.title.to_owned(),
"lang" => self.lang.to_owned(),
"description" => self.description.to_owned(),
"slug" => self.slug.to_owned(),
"body" => self.html_body.to_owned(),
"css" => self.css_src.as_ref().unwrap_or(&String::new()).to_owned(),
"js" => self.js_src.as_ref().unwrap_or(&String::new()).to_owned(),
_ => String::new(),
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct PagesTree {
pub page_data: PageData,
pub sub_pages: Option<Vec<PagesTree>>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct WebSite {
pages_tree: PagesTree,
}
impl WebSite {
pub fn new(pages_tree: PagesTree) -> Self {
let mut pages_index_by_url = HashMap::new();
WebSite::create_index_by_url(&mut pages_index_by_url, &pages_tree, PathBuf::from("/"));
WebSite {
pages_tree,
pages_index_by_url,
}
}
pub fn from_json_str(json: &str) -> Self {
WebSite::new(serde_json::from_str(json).unwrap())
}
if let Some(sub_pages) = &pages_tree.sub_pages {
for pt in sub_pages {
pub fn get_page_by_url(&self, url: &PathBuf) -> Option<&WebPage> {
self.pages_index_by_url.get(&PathBuf::from("/").join(url))
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
}
}
#[cfg(test)]
mod test_website {
use super::*;
const JSON_TEMPLATE: &'static str = "
{
\"page_data\": {
\"title\": \"Test Website\",
\"slug\": \"\",
\"lang\": \"en\",
\"description\": \"A test website\",
\"html_body\": \"<h1>Test Website</h1>\"
},
\"sub_pages\": [
{
\"page_data\": {
\"title\": \"A sub page\",
\"slug\": \"subpage\",
\"lang\": \"en\",
\"description\": \"A sub page of the testing web site\",
\"html_body\": \"<h1>A sub page</h1>\"
},
\"sub_pages\": [
{
\"page_data\": {
\"slug\": \"nested\",
\"description\": \"Nested testing page\",
\"html_body\": \"<h1>Nested page</h1>\"
}
}
]
}
]
}
";
#[test]
fn test_index_pages_by_slug() {
let website = WebSite::from_json_str(JSON_TEMPLATE);
let root_page = website.get_page_by_url(&PathBuf::from("/"));
assert!(root_page.is_some());
let root_page = root_page.unwrap();
assert_eq!(root_page.page_data.html_body, "<h1>Test Website</h1>");
let sub_page = website.get_page_by_url(&PathBuf::from("subpage"));
assert!(sub_page.is_some());
let sub_page = sub_page.unwrap();
assert_eq!(sub_page.page_data.html_body, "<h1>A sub page</h1>");
let nested_page = website.get_page_by_url(&PathBuf::from("subpage/nested"));
assert!(nested_page.is_some());
let nested_page = nested_page.unwrap();
assert_eq!(nested_page.page_data.html_body, "<h1>Nested page</h1>");