From 9db2df55c10a6b53983b492b40798e086fce9a69 Mon Sep 17 00:00:00 2001
From: Pierre Jarriges <pierre.jarriges@tutanota.com>
Date: Tue, 27 Sep 2022 10:48:22 +0200
Subject: [PATCH] fix page body serialization

---
 src/website/html.rs |  1 +
 src/website/page.rs | 60 +++++++++++++++++++++++++++++++++++----------
 2 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/src/website/html.rs b/src/website/html.rs
index 383945e..031ebad 100644
--- a/src/website/html.rs
+++ b/src/website/html.rs
@@ -22,6 +22,7 @@ const HTML_DOC_TEMPLATE: &'static str = "
     <meta property='og:title' content='{title}'/>
     <meta property='og:description' content='{description}'/>
     {image}
+    {favicon}
     <title>{title}</title>
     {css}
 </head>
diff --git a/src/website/page.rs b/src/website/page.rs
index 7be9be6..94a7b97 100644
--- a/src/website/page.rs
+++ b/src/website/page.rs
@@ -4,14 +4,18 @@ use super::html::{
     IMAGE_LINKS_FRAGMENT, SCRIPT_FRAGMENT,
 };
 use crate::StaticFilesManager;
-use serde::{Deserialize, Serialize};
+use serde::{
+    ser::{SerializeStruct, Serializer},
+    Deserialize, Serialize,
+};
 use std::collections::HashMap;
 use std::path::PathBuf;
 
-#[derive(Debug, Serialize, Deserialize, Clone)]
+#[derive(Debug, Deserialize, Clone)]
 pub struct Page {
     pub template_name: String,
     pub body: PageBody,
+    pub full_body: Option<PageBody>,
     pub metadata: PageMetadata,
     #[serde(default = "Vec::new")]
     pub sub_pages: Vec<Page>,
@@ -20,6 +24,22 @@ pub struct Page {
     pub template: Option<PageTemplate>,
 }
 
+impl Serialize for Page {
+    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
+    where
+        S: Serializer,
+    {
+        let mut state = serializer.serialize_struct("Page", 5)?;
+        state.serialize_field("template_name", &self.template_name)?;
+        state.serialize_field("body", &self.body)?;
+        state.serialize_field("metadata", &self.metadata)?;
+        state.serialize_field("sub_pages", &self.sub_pages)?;
+        state.serialize_field("template", &self.template)?;
+
+        state.end()
+    }
+}
+
 #[derive(Debug, Serialize, Deserialize, Clone)]
 pub struct PageTemplate {
     pub layout: StyleSheet,
@@ -86,7 +106,7 @@ pub struct FaviconLink(String);
 
 impl FaviconLink {
     pub fn new() -> Self {
-        FaviconLink(String::from("/default/favicon.ico"))
+        FaviconLink(String::from("/assets/default/favicon.ico"))
     }
 }
 
@@ -137,7 +157,7 @@ pub struct JSLinks(Vec<String>);
 
 impl JSLinks {
     pub fn new() -> Self {
-        JSLinks(vec!["/default/script.js".to_owned()])
+        JSLinks(vec!["/assets/default/script.js".to_owned()])
     }
 }
 
@@ -195,7 +215,8 @@ impl Page {
         parent_scope: PathBuf,
         static_files_manager: &StaticFilesManager,
     ) -> Result<(), String> {
-        self.build_with_template(self.template(templates));
+        self.set_template(self.template(templates).clone());
+        self.build_full_body();
         self.build_html();
         let url = self.url(parent_scope);
 
@@ -218,19 +239,23 @@ impl Page {
         Ok(())
     }
 
+    pub fn set_template(&mut self, template: PageTemplate) {
+        self.template = Some(template);
+    }
+
     fn build_html(&mut self) {
         self.html = HtmlDoc::from_page(self);
     }
 
-    fn build_with_template(&mut self, template: &PageTemplate) {
-        let mut complete_body = template.clone();
-        self.template = Some(template.clone());
+    fn build_full_body(&mut self) {
+        let mut full_body = self.template.clone().expect("Page template is not set");
 
-        PageTemplate::get_page_body_placeholder(&mut complete_body.contents)
+        // insert the page body elements in the template page-body container.
+        PageTemplate::get_page_body_placeholder(&mut full_body.contents)
             .expect("Couldn't find page body container in template")
             .set_contents(self.body.0.clone());
 
-        self.body.0 = complete_body.contents;
+        self.full_body = Some(PageBody(full_body.contents));
     }
 
     fn url(&self, parent_scope: PathBuf) -> PathBuf {
@@ -260,10 +285,17 @@ impl Page {
             self.metadata.description.to_owned(),
         );
         map.insert("slug".to_string(), self.metadata.url_slug.to_owned());
-        map.insert("body".to_string(), self.body.to_string());
+        map.insert(
+            "body".to_string(),
+            self.full_body
+                .as_ref()
+                .expect("Page full body is not built")
+                .to_string(),
+        );
         map.insert("css".to_string(), self.metadata.css.to_string());
         map.insert("js".to_string(), self.metadata.js.to_string());
         map.insert("author".to_string(), self.metadata.author.to_string());
+        map.insert("favicon".to_string(), self.metadata.favicon.to_string());
         map.insert("image".to_string(), self.metadata.image.to_string());
 
         map
@@ -351,6 +383,7 @@ mod test_pages {
                 contents: None,
                 attrs: HtmlAttributes::new(),
             }]),
+            full_body: None,
             metadata: test_page_metadata(),
             sub_pages: Vec::new(),
             html: HtmlDoc::new(),
@@ -424,9 +457,10 @@ mod test_pages {
     #[test]
     fn build_body_with_template() {
         let mut page = test_page();
-        page.build_with_template(&test_page_template());
+        page.set_template(test_page_template());
+        page.build_full_body();
         assert_eq!(
-            page.body.to_string(),
+            page.full_body.unwrap().to_string(),
             "<div id=\"test-template\"><nav>NAV</nav><div id=\"page-body\"><span>TEST</span></div><footer>FOOTER</footer></div>"
         )
     }
-- 
GitLab