Readme.md - added Section for customization and notes
[biaweb2.git] / biawebdocument.hpp
index 9829bcd..3972107 100644 (file)
@@ -5,10 +5,14 @@
 #include <string>
 #include <list>
 #include <memory>
+#include <iomanip>
 #include <ctime>
+#include <fmt/format.h>
 #include "biawebutil.hpp"
 #include "biawebsidebar.hpp"
 #include "biawebstrings.hpp"
+#include "biawebnavigationbit.hpp"
+#include "biawebtemplate.hpp"
 
 // class to represent a biaweb document which can have a file name, title, description, 
 // keywords, content and sidebar items
@@ -21,7 +25,8 @@ namespace biaweb {
         std::string meta_desc;
         std::string meta_keywords;
         std::string content;
-        std::list<SideBar> sidebars; 
+        std::list<SideBar> sidebars;
+        NavigationBit navbit; 
         std::time_t cdate;
         std::time_t mdate;
         bool is_index;
@@ -32,9 +37,9 @@ namespace biaweb {
                         bool is_index = false, std::time_t cdate= std::time(nullptr),
                             std::time_t mdate = std::time(nullptr))
         {
-            this->title = title;
-            this->meta_desc = meta_desc;
-            this->meta_keywords = meta_keywords;
+            this->title = escape_html (title);
+            this->meta_desc = escape_html (meta_desc);
+            this->meta_keywords = escape_html (meta_keywords);
             this->content = content;
             this->is_index = is_index;
             if (! is_index)
@@ -45,6 +50,20 @@ namespace biaweb {
             this->mdate = mdate;
         }
 
+        // Constructor to parse the document from a stream instead of manually creating it 
+        // File should be of the format
+        // first line: title
+        // second line: Description
+        // third line: Keywords 
+        // fourth line: (creation date) YYYY-MM-DD HH:II TZ format
+        // fourth line onwards: Markdown contents
+        Document (std::istream &file) ;
+
+        // set the navigation bit
+        void set_navigation_bit (NavigationBit navbit) {
+            this->navbit = navbit;
+        }
+
         // set whether this is the index document
         void set_index (bool index = true) {
             this->is_index = index; 
@@ -82,8 +101,8 @@ namespace biaweb {
             return this->cdate;
         }
 
-        // output the document to HTML using the templates in templatedir
-        void output_to_html (std::string templatedir, std::string path); 
+        // output the document to HTML using the template specified
+        void output_to_html (Template *t, std::string path); 
 
         // set the content portion of document as raw HTML content
         void set_content (std::string content) {
@@ -95,11 +114,11 @@ namespace biaweb {
         void set_markdown_content (std::string str); 
 
         void set_meta_keywords(std::string meta_keywords) {
-            this->meta_keywords = meta_keywords;
+            this->meta_keywords = escape_html (meta_keywords);
         }
         
         void set_meta_desc(std::string meta_desc) {
-            this->meta_desc = meta_desc;
+            this->meta_desc = escape_html (meta_desc);
         }
         
         void set_title(std::string title) {
@@ -131,47 +150,85 @@ namespace biaweb {
         }
     };
 
+    // Parse and construct a document from a stream instead of individual fields
+    Document::Document (std::istream &infile) {
+        infile.seekg (0);
+        // parse the title, description, keywords, creation time and and contents
+        std::string title, description, keywords, creattime, contents;
+        // read the title
+        std::getline (infile, title);
+        if (infile.eof ()) return;
+        this->title = escape_html (title);
+        this->filename = convert_title (title);
+        // read description
+        std::getline (infile, description);
+        if (infile.eof ()) return;
+        this->meta_desc = escape_html (description);
+        // read the keywords
+        std::getline (infile, keywords);
+        if (infile.eof ()) return;
+        this->meta_keywords = escape_html (keywords); 
+        // read the creation date/time and also set the modification time
+        // to creation date/time by default
+        std::getline (infile, creattime);
+        if (infile.eof ()) return; 
+        std::stringstream s (creattime);
+        std::tm t;
+        s >> std::get_time (&t, DATE_IN_FORMAT);
+        if (s.fail ())
+            std::cout << WARNING_PARSE_FAILED << this->filename << "\n";
+        this->cdate = mktime (&t);
+        this->mdate = this->cdate;
+        // read the rest of contents
+        std::string line;
+        while (! infile.eof ()) {
+            std::getline (infile, line);
+            contents.append (line + "\n");
+        }
+        this->set_markdown_content (contents);
+    }
+
     void Document::set_markdown_content (std::string str) {
         this->content = convert_to_markdown (str);
     }
     
-    void Document::output_to_html (std::string templatedir, std::string path)
+    // output the document using the provided template
+    void Document::output_to_html (Template *t, std::string path)
     {
-        std::ifstream tpl;
-        tpl.open (templatedir + "/main.tpl.html");
-        std::string main_tpl ( (std::istreambuf_iterator<char> (tpl)),
-                                (std::istreambuf_iterator<char> ()) );
-        tpl.close ();
+        std::string templstr = t->get_main_tpl ();
+
+        // read the style template file
+        std::string stylesheet = t->get_style_tpl ();
         // first render the sidebars
         std::string sidebartext;
         for (SideBar bar : sidebars) {
-            sidebartext += bar.to_html (templatedir);
-        }
-
-        char ctm_str[100], mtm_str[100];
-        std::time_t creat = this->cdate;
-        std::time_t modif = this->cdate;
-        std::strftime (ctm_str, sizeof (ctm_str), 
-                        DATE_FORMAT, std::localtime (&creat));
-        std::strftime (mtm_str, sizeof (mtm_str),
-                        DATE_FORMAT, std::localtime (&modif));
-        
-        // Allocate enough space for the output buffer
-        std::unique_ptr<char[]> final_templ(
-                                    new char[main_tpl.size()+
-                                            this->title.size()+
-                                            this->content.size() +
-                                            this->meta_desc.size() +
-                                            this->meta_keywords.size () +
-                                            200 +
-                                            sidebartext.size()]);
-        std::sprintf (final_templ.get (), main_tpl.c_str(), this->title.c_str(), 
-                this->meta_keywords.c_str(), this->meta_desc.c_str (),
-                ctm_str, mtm_str, 
-                this->content.c_str(), sidebartext.c_str());
+            sidebartext += bar.to_html (t);
+        }
+
+        // render the navigation bit
+        std::string navbit_str = this->navbit.to_html (t);
+
+        // time of creation and modification 
+        struct std::tm c, m;
+        c = *std::localtime (&this->cdate);
+        m = *std::localtime (&this->mdate);
+
+        // format the template with the values
+        std::string outputhtml = fmt::format (templstr, 
+                                    fmt::arg ("title", this->title),
+                                    fmt::arg ("keywords", this->meta_keywords), 
+                                    fmt::arg ("stylesheet", stylesheet),
+                                    fmt::arg ("description", this->meta_desc),
+                                    fmt::arg ("cdate", c),
+                                    fmt::arg ("mdate", m),
+                                    fmt::arg ("navbit", navbit_str),
+                                    fmt::arg ("contents", this->content),
+                                    fmt::arg ("sidebar", sidebartext)
+                                    );
 
         std::ofstream f (path + "/" + this->filename + ".html");
-        f << final_templ.get ();
+        f << outputhtml;
         f.close ();
     }
 }