From 1d1f04629b04c7e7efd14d8f281e17f5e491c888 Mon Sep 17 00:00:00 2001 From: Harishankar Date: Mon, 18 May 2020 16:24:08 +0530 Subject: [PATCH] Tree Website generation implemented Completed the functionality to generate the HTML tree from a source tree, using templates. TODO: further refinement of generated HTML code --- biaweb.cpp | 60 +++++++++++++++++----------- biawebdocument.hpp | 15 +++---- biawebdocumenttree.hpp | 91 +++++++++++++++++++++++++++++++++++++----- biawebsidebar.hpp | 19 ++++----- biawebutil.hpp | 3 +- 5 files changed, 134 insertions(+), 54 deletions(-) diff --git a/biaweb.cpp b/biaweb.cpp index ca9c059..0422995 100644 --- a/biaweb.cpp +++ b/biaweb.cpp @@ -5,31 +5,43 @@ using namespace biaweb; int main (int argc, char *argv[]) { - if (argc == 2) - { - std::shared_ptr 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 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 a1 (new DocumentTree("Child a1")); - std::shared_ptr a2 (new DocumentTree("Child a2")); - std::shared_ptr a3 (new DocumentTree("Child a3")); - std::shared_ptr a4 (new DocumentTree("Child a4")); - std::shared_ptr 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] << "
" << std::endl; +// std::shared_ptr a1 (new DocumentTree("Child a1")); +// std::shared_ptr a2 (new DocumentTree("Child a2")); +// std::shared_ptr a3 (new DocumentTree("Child a3")); +// std::shared_ptr a4 (new DocumentTree("Child a4")); +// std::shared_ptr d2 (new Document ("Another document")); +// d2.get()->set_creation_date (124012); +// std::shared_ptr 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] << "
" << 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; diff --git a/biawebdocument.hpp b/biawebdocument.hpp index b79b346..edfed7e 100644 --- a/biawebdocument.hpp +++ b/biawebdocument.hpp @@ -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 -} // 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 (tpl)), (std::istreambuf_iterator ()) ); 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]; diff --git a/biawebdocumenttree.hpp b/biawebdocumenttree.hpp index a65e334..608b702 100644 --- a/biawebdocumenttree.hpp +++ b/biawebdocumenttree.hpp @@ -4,8 +4,10 @@ #include #include #include +#include #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 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 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 (infile)), + (std::istreambuf_iterator ())); + // 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 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); } } diff --git a/biawebsidebar.hpp b/biawebsidebar.hpp index 75761da..a5ccef6 100644 --- a/biawebsidebar.hpp +++ b/biawebsidebar.hpp @@ -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 (tpl_linkitem)), (std::istreambuf_iterator ())); 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 (tpl_item)), (std::istreambuf_iterator ())); 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 (sidetpl)) , (std::istreambuf_iterator ())); 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 tpl_final (new char[sidetpl_str.size() + diff --git a/biawebutil.hpp b/biawebutil.hpp index b519615..ee6cd5a 100644 --- a/biawebutil.hpp +++ b/biawebutil.hpp @@ -1,6 +1,7 @@ #ifndef __BIAWEBUTIL__ #define __BIAWEBUTIL__ #include + // "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 -- 2.20.1