Tree Website generation implemented
authorHarishankar <v.harishankar@gmail.com>
Mon, 18 May 2020 10:54:08 +0000 (16:24 +0530)
committerHarishankar <v.harishankar@gmail.com>
Mon, 18 May 2020 10:54:08 +0000 (16:24 +0530)
Completed the functionality to generate the HTML tree from a
source tree, using templates. TODO: further refinement of
generated HTML code

biaweb.cpp
biawebdocument.hpp
biawebdocumenttree.hpp
biawebsidebar.hpp
biawebutil.hpp

index ca9c059..0422995 100644 (file)
@@ -5,31 +5,43 @@ using namespace biaweb;
 
 int main (int argc, char *argv[]) {
 
-    if (argc == 2)
-    {
-        std::shared_ptr<DocumentTree> tree (new DocumentTree (argv[1]));
-        tree.get()->set_stub ("");
-        tree.get()->set_markdown_summary ("# Hello there\n\n\
-These are some contents for this page.");
+//     if (argc == 2)
+//     {
+//         std::shared_ptr<DocumentTree> tree (new DocumentTree (argv[1]));
+//         tree.get()->set_stub ("");
+//         tree.get()->set_markdown_summary ("# Hello there\n\n\
+// These are some contents for this page.");
 
-        std::shared_ptr<DocumentTree> a1 (new DocumentTree("Child a1"));
-        std::shared_ptr<DocumentTree> a2 (new DocumentTree("Child a2"));
-        std::shared_ptr<DocumentTree> a3 (new DocumentTree("Child a3"));
-        std::shared_ptr<DocumentTree> a4 (new DocumentTree("Child a4"));
-        std::shared_ptr<Document> d1 (new Document("Test Document", "", 
-                                                ""));
-        d1.get()->set_markdown_content ("# Heading \n\nThis is some text, hello world");
-        a1.get()->add_document (d1.get());
-        a3.get()->add_child (a4.get());    
-        a1.get()->add_child (a2.get());
-        a1.get()->add_child (a3.get());
-        tree.get()->add_child (a1.get());
-        std::cout << a3.get()->stub_hierarchy () << a3.get()->get_stub () << std::endl;
-        tree.get()->visualize_tree ();
-        tree.get()->create_tree_html (convert_title (argv[1]));
-    }
-    else
-        std::cout << "Usage: " << argv[0] << " <main tree>" << std::endl;
+//         std::shared_ptr<DocumentTree> a1 (new DocumentTree("Child a1"));
+//         std::shared_ptr<DocumentTree> a2 (new DocumentTree("Child a2"));
+//         std::shared_ptr<DocumentTree> a3 (new DocumentTree("Child a3"));
+//         std::shared_ptr<DocumentTree> a4 (new DocumentTree("Child a4"));
+//         std::shared_ptr<Document> d2 (new Document ("Another document"));
+//         d2.get()->set_creation_date (124012);
+//         std::shared_ptr<Document> d1 (new Document("Test Document"));
+//         d1.get()->set_creation_date (100000);
+//         d1.get()->set_markdown_content ("# Heading \n\nThis is some text, hello world");
+//         d2.get()->set_markdown_content ("Some document \n\nThis is some document");
+//         a1.get()->add_document (d2.get());
+//         a1.get()->add_document (d1.get());
+//         a3.get()->add_child (a4.get());    
+//         a1.get()->add_child (a2.get());
+//         a1.get()->add_child (a3.get());
+//         tree.get()->add_child (a1.get());
+//         std::cout << a3.get()->stub_hierarchy () << a3.get()->get_stub () << std::endl;
+//         tree.get()->visualize_tree ();
+//         tree.get()->create_tree_html ("/home/hari/Projects/BiaWeb2/templates", 
+//                             convert_title (argv[1]));
+//     }
+// //     else {
+// //         std::cout << "Usage: " << argv[0] << " <main tree>" << std::endl;
+
+    DocumentTree tree (""); 
+    tree.document_tree_builder ("/home/hari/Projects/BiaWeb2/Test/In");
+    tree.visualize_tree ();
+    tree.create_tree_html ("/home/hari/Projects/BiaWeb2/templates", 
+                        "Test/Out");
+// //   }
 
     // Document doc;
     // SideBar items;
index b79b346..edfed7e 100644 (file)
@@ -9,11 +9,6 @@
 #include "biawebutil.hpp"
 #include "biawebsidebar.hpp"
 
-// "discount" markdown library is a C library and hence requires to be wrapped in 
-// extern "C"
-extern "C" {
-    #include <mkdio.h>
-}
 // class to represent a biaweb document which can have a file name, title, description, 
 // keywords, content and sidebar items
 namespace biaweb {
@@ -86,8 +81,8 @@ namespace biaweb {
             return this->cdate;
         }
 
-        // output the document to HTML using the template
-        void output_to_html (std::string path); 
+        // output the document to HTML using the templates in templatedir
+        void output_to_html (std::string templatedir, std::string path); 
 
         // set the content portion of document as raw HTML content
         void set_content (std::string content) {
@@ -139,17 +134,17 @@ namespace biaweb {
         this->content = convert_to_markdown (str);
     }
     
-    void Document::output_to_html (std::string path)
+    void Document::output_to_html (std::string templatedir, std::string path)
     {
         std::ifstream tpl;
-        tpl.open ("templates/main.tpl.html", std::ios_base::openmode::_S_in);
+        tpl.open (templatedir + "/main.tpl.html", std::ios_base::openmode::_S_in);
         std::string main_tpl ( (std::istreambuf_iterator<char> (tpl)),
                                 (std::istreambuf_iterator<char> ()) );
         tpl.close ();
         // first render the sidebars
         std::string sidebartext;
         for (SideBar bar : sidebars) {
-            sidebartext += bar.to_html ();
+            sidebartext += bar.to_html (templatedir);
         }
 
         char ctm_str[100], mtm_str[100];
index a65e334..608b702 100644 (file)
@@ -4,8 +4,10 @@
 #include <list>
 #include <iostream>
 #include <filesystem>
+#include <sys/stat.h>
 #include "biawebdocument.hpp"
 #include "biawebstrings.hpp"
+#include "biawebutil.hpp"
 
 // to implement a document tree - both with or without subtrees
 namespace biaweb {
@@ -31,6 +33,9 @@ namespace biaweb {
         }
 
       public:
+        // method to build a document tree from a path
+        void document_tree_builder (std::string srcpath);
+
         // create new top level document tree
         DocumentTree (std::string title, std::string stub = "") {
             this->title = title;
@@ -57,8 +62,14 @@ namespace biaweb {
             return this->summary;
         }
 
+        // sort the documents as per creation time from latest to oldest
+        void sort_documents_creation_time () {
+            this->docs.sort ([] (Document &a, Document &b) 
+                    {return (a.get_creation_date() > b.get_creation_date()); });
+        }
+
         // create the document index for this tree
-        void create_tree_html (std::string destdir);
+        void create_tree_html (std::string templatedir, std::string destdir);
 
         // set the title 
         void set_title (std::string title) {
@@ -142,15 +153,15 @@ namespace biaweb {
             for (unsigned int i = 0; i < this->get_level(); i ++)
                 std::cout <<  "+--";
             // print the title of this tree
-            std::cout << this->title << std::endl;
+            std::cout << this->title << std::endl;            
             // recurse through the child trees if any and so on
             for (DocumentTree child : children)
                 child.visualize_tree ();
     }
 
     // create the tree - the index file for this tree and all the documents and
-    // the child trees recursively
-    void DocumentTree::create_tree_html (std::string destdir) {
+    // the child trees recursively - using the template specified
+    void DocumentTree::create_tree_html (std::string templatedir, std::string destdir) {
         std::unique_ptr<Document> index (new Document (this->title));
         index.get()->set_index ();
         // set the file name path
@@ -202,24 +213,84 @@ namespace biaweb {
         // add it to the content portion  
         SideBar article_list;
         article_list.set_title (this->title + ": " + ART_LIST);
+        // sort the documents as per creation time and then add the document
+        // links - newest documents should appear above older ones.
+        sort_documents_creation_time ();
         for (Document doc : this->docs) {
             SideBarItem item;
             item.set_sidebar_text (doc.get_title());
             item.set_sidebar_url (urlpath + doc.get_filename() + ".html");
             article_list.add_sidebar_item (item);
             // output the document also, add the side bars
-            if (this->get_parent() != nullptr)
-                doc.add_side_bar (*bar1.get());
+            doc.add_side_bar (*bar1.get());
             doc.add_side_bar (*bar2.get());
-            doc.output_to_html (filepath);
+            doc.output_to_html (templatedir, filepath);
         }
-        index.get()->set_content (this->summary + article_list.to_html());
+        index.get()->set_content (this->summary + article_list.to_html(templatedir));
 
-        index.get()->output_to_html (filepath);
+        index.get()->output_to_html (templatedir, filepath);
 
         // create index for children
         for (DocumentTree tree : this->children)
-            tree.create_tree_html (destdir);
+            tree.create_tree_html (templatedir, destdir);
+    }
+
+    // build a document tree from a filesystem path recursively
+    void DocumentTree::document_tree_builder (std::string srcpath_str) {
+        std::filesystem::path srcpath (srcpath_str);
+        this->title = srcpath.stem().string ();
+
+        // Get the directories to this child and add them as sub document
+        // trees
+        try {
+            for (auto fsitem : std::filesystem::directory_iterator (srcpath) )
+            {
+                // if it is a directory then build the tree for that directory
+                if (fsitem.is_directory ()) {
+                    std::shared_ptr <DocumentTree> doctree 
+                                    (new DocumentTree (fsitem.path().filename().string()));
+                    
+                    this->add_child (doctree.get());
+                }
+                // add the regular files as documents in the tree
+                else if (fsitem.is_regular_file ()) {
+                    // read the contents of the file
+                    std::ifstream infile (fsitem.path().string());
+                    std::string infilestr ((std::istreambuf_iterator<char> (infile)),
+                                            (std::istreambuf_iterator<char> ()));
+                    // if it is an index file (specially named index) add 
+                    // the contents to the summary of the Doctree 
+                    if (fsitem.path().stem().string() == "index")
+                    {
+                        this->set_markdown_summary (infilestr);
+                    }
+                    // else it is a non-index file-  
+                    // create a Document and add it to the tree
+                    else {
+                        std::shared_ptr<Document> doc 
+                                (new Document (fsitem.path().stem().string()));
+                        
+                        // file creation/modified date from system
+                        struct stat buf;
+                        if (stat (fsitem.path().string().c_str(), &buf) == 0)
+                        {
+                            doc.get()->set_creation_date (buf.st_ctim.tv_sec);
+                            doc.get()->set_modified_date (buf.st_mtim.tv_sec);
+                        }
+                        doc.get()->set_markdown_content (infilestr);
+
+                        this->add_document (doc.get());
+                    }
+                }
+            }
+        }
+        catch (std::filesystem::filesystem_error) {
+            std::cout << "No such path! Specify an existing file path" << std::endl;
+        }
+
+        // add the trees for the children recursively
+        for (DocumentTree &child : this->children)
+            child.document_tree_builder (srcpath_str + "/" + child.title);
     }
 }
 
index 75761da..a5ccef6 100644 (file)
@@ -29,7 +29,8 @@ namespace biaweb {
         void set_sidebar_url (std::string url) {
             this->sidebar_url = url;
         }
-        std::string to_html ();
+        // output to HTML using a template directory specified
+        std::string to_html (std::string templatedir);
     
         SideBarItem (std::string text = "", std::string url = "") {
             this->sidebar_text = text;
@@ -37,13 +38,13 @@ namespace biaweb {
         }
     };
 
-    std::string SideBarItem::to_html () {
+    std::string SideBarItem::to_html (std::string templatedir) {
         std::string html;
         // if url is not empty it is a link item so load the sidebar link template
         if (! this->sidebar_url.empty ()) {
             if (!this->sidebar_text.empty ())
             {
-                std::ifstream tpl_linkitem ("templates/sidebarlinkitem.tpl.html");
+                std::ifstream tpl_linkitem (templatedir + "/sidebarlinkitem.tpl.html");
                 std::string tpl_linkitem_str ( (std::istreambuf_iterator<char> (tpl_linkitem)),
                                                 (std::istreambuf_iterator<char> ()));
                 tpl_linkitem.close ();
@@ -62,7 +63,7 @@ namespace biaweb {
         // Non link item. Load the normal sidebar item template.
         else
         {
-            std::ifstream tpl_item ("templates/sidebaritem.tpl.html");
+            std::ifstream tpl_item (templatedir + "/sidebaritem.tpl.html");
             std::string tpl_item_str ( (std::istreambuf_iterator<char> (tpl_item)),
                                         (std::istreambuf_iterator<char> ()));
             tpl_item.close ();
@@ -90,20 +91,20 @@ namespace biaweb {
             items.insert (items.cend(), item);
         }
 
-        // render the sidebar
-        std::string to_html () ;
+        // render the sidebar using the template directory specified
+        std::string to_html (std::string templatedir) ;
     };
 
     // render the sidebar to HTML representation from the template.
-    std::string SideBar::to_html () {
-        std::ifstream sidetpl ("templates/sidebar.tpl.html");
+    std::string SideBar::to_html (std::string templatedir) {
+        std::ifstream sidetpl (templatedir + "/sidebar.tpl.html");
         std::string sidetpl_str ( ( std::istreambuf_iterator<char> (sidetpl)) , 
                                        (std::istreambuf_iterator<char> ()));
         sidetpl.close ();
         std::string listitem;
         // first get the sidebar items and render them to HTML
         for (SideBarItem item : items) {
-            listitem += item.to_html ();
+            listitem += item.to_html (templatedir);
         }
 
         std::unique_ptr<char[]> tpl_final (new char[sidetpl_str.size() + 
index b519615..ee6cd5a 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __BIAWEBUTIL__
 #define __BIAWEBUTIL__
 #include <string>
+
 // "discount" markdown library is a C library and hence requires to be wrapped in 
 // extern "C"
 extern "C" {
@@ -10,8 +11,8 @@ extern "C" {
 // utility functions for Biaweb that don't fit into any class and can be used by 
 // any class
 namespace biaweb {
-    // convert markdown
 
+    // convert markdown
     std::string convert_to_markdown (std::string str) {
         // discount is a C library and it doesn't work well with C++ streams
         // and there seems no way to get the output of any of these functions