X-Git-Url: https://harishankar.org/repos/?p=biaweb2.git;a=blobdiff_plain;f=biawebdocumenttree.hpp;h=a9f1ccd90dd40cc6e6b7919f30c024783c06cecc;hp=a65e334cc75667cb1e1248f560297448128cfb5a;hb=HEAD;hpb=f56e2150cc79638c890ef23ef82097a4bdffd2ce diff --git a/biawebdocumenttree.hpp b/biawebdocumenttree.hpp index a65e334..a9f1ccd 100644 --- a/biawebdocumenttree.hpp +++ b/biawebdocumenttree.hpp @@ -2,12 +2,19 @@ #define __BIAWEBDOCUMENTTREE__ #include #include +#include #include +#include #include +#include #include "biawebdocument.hpp" #include "biawebstrings.hpp" +#include "biawebutil.hpp" +#include "biawebdoclist.hpp" +#include "biawebtemplate.hpp" +#include "biawebrss.hpp" -// to implement a document tree - both with or without subtrees +// class to implement a document tree - both with or without subtrees namespace biaweb { class DocumentTree { protected: @@ -31,9 +38,12 @@ 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; + this->title = escape_html (title); // if stub is not empty set it if (stub != "") this->stub = stub; @@ -57,12 +67,18 @@ 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 (Template *t, std::string destdir); // set the title void set_title (std::string title) { - this->title = title; + this->title = escape_html (title); // if no stub is set if (this->stub == "") this->stub = convert_title (title); @@ -142,15 +158,17 @@ 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 (Template *tpl, std::string destdir) { + + // create a document to represent the index of the tree. std::unique_ptr index (new Document (this->title)); index.get()->set_index (); // set the file name path @@ -168,58 +186,164 @@ namespace biaweb { // Create a link to the index page and // If this tree has a parent, create a sidebar link to the level up std::unique_ptr bar1 (new SideBar()); - SideBarItem item0; - item0.set_sidebar_text (INDEX); - item0.set_sidebar_url (urlpath + "index.html"); + GenericLinkItem item0; + bar1.get()->set_title (tpl->get_stringbit (NAVIGATION)); + item0.set_item_text (tpl->get_stringbit (INDEX)); + item0.set_item_url (urlpath + "index.html"); bar1.get()->add_sidebar_item (item0); if (this->get_parent() != nullptr) { - SideBarItem item1; - item1.set_sidebar_text (GO_UP); - item1.set_sidebar_url (this->stub_hierarchy() + "index.html"); + GenericLinkItem item1; + item1.set_item_text (tpl->get_stringbit(GO_UP)); + item1.set_item_url (this->stub_hierarchy() + "index.html"); bar1.get()->add_sidebar_item (item1); } - index.get()->add_side_bar (*bar1.get()); - + // create a sidebar for the child levels if there are children std::unique_ptr bar2 (new SideBar ()); - bar2.get()->set_title (SUB_CAT + this->title); + bar2.get()->set_title (tpl->get_stringbit (SUB_CAT) + this->title); for (DocumentTree tree : this->children) { // we use site relative URLs that rely on the base href tag // so for biaweb generated sites, the base href tag should be // used in the main template - SideBarItem item (tree.get_title(), urlpath + + GenericLinkItem item (tree.get_title(), urlpath + tree.stub + "/" + "index.html"); bar2.get()->add_sidebar_item (item); } - index.get()->add_side_bar (*bar2.get()); // create the path and then the index file std::filesystem::create_directories (filepath); // Create the list of documents in this tree with links - // Reuse the sidebar class and sidebaritem class which is - // basically a list of links but instead of adding a sidebar - // add it to the content portion - SideBar article_list; - article_list.set_title (this->title + ": " + ART_LIST); + std::unique_ptr article_list (new DocList ()); + article_list.get()->set_title (this->title + ": " + tpl->get_stringbit (ARTICLES_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 (); + + // create the navigation bit + std::shared_ptr navbit (new NavigationBit ()); + auto par1 = this; + // get the link to each level in the hierarchy and add it as + // an inline list + while (par1 != nullptr) { + if (par1->parent != nullptr) + navbit.get()->add_link_item (GenericLinkItem(par1->title, + par1->stub_hierarchy() + par1->stub + "/index.html")); + else + navbit.get()->add_link_item (GenericLinkItem(tpl->get_stringbit(HOME), "index.html")); + par1 = par1->parent; + } + + // rss feed + std::unique_ptr feed (new RSSFeed ()); + feed.get()->set_pub_date (index.get()->get_creation_date()); + feed.get()->set_title (this->get_title()); + + // iterate through the documents and generate the document 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()); + // Add the document to RSS feed + RSSFeedItem fitem (doc.get_title(), doc.get_meta_desc (), + urlpath + doc.get_filename() + ".html", + doc.get_creation_date()); + // If the items don't exceed max size of RSS feed + if (feed.get()->get_num_items() < MAX_RSS_FEED) + feed.get()->add_rss_item (fitem); + // Add the document details to the document list + DocListItem item (&doc, urlpath); + article_list.get()->add_document_item (item); + // output the document also, add the navigation bit and side bars + + doc.set_navigation_bit (*navbit.get()); + doc.add_side_bar (*bar1.get()); doc.add_side_bar (*bar2.get()); - doc.output_to_html (filepath); + doc.output_to_html (tpl, filepath); + } + + // output the rss feed + feed.get()->output_to_html (tpl, filepath); + + // add the side bars + index.get()->add_side_bar (*bar1.get()); + index.get()->add_side_bar (*bar2.get()); + + // sidebar for RSS feed + // if there are are items in the feed add the link + if (feed.get()->get_num_items () > 0) { + std::unique_ptr bar3 (new SideBar ()); + bar3.get()->set_title (tpl->get_stringbit (SUBSCRIBE)); + bar3.get()->add_sidebar_item ( + GenericLinkItem (tpl->get_stringbit(RSS_FEED), urlpath + "feed.xml")); + index.get()->add_side_bar (*bar3.get()); } - index.get()->set_content (this->summary + article_list.to_html()); - index.get()->output_to_html (filepath); + // add the navigation bit + index.get()->set_navigation_bit (*navbit.get()); + // index should contain the summary followed by the the article list + // and the sub categories + index.get()->set_content (this->summary + + article_list.get()->to_html(tpl) + + bar2.get()->to_html (tpl)); + + // output the index file + index.get()->output_to_html (tpl, filepath); - // create index for children + // recursively create index for children for (DocumentTree tree : this->children) - tree.create_tree_html (destdir); + tree.create_tree_html (tpl, 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 and not symlink + else if (fsitem.is_regular_file () && !fsitem.is_symlink()) { + // if it is an index file (specially named as index + // or index.md or whatever) directly add + // the contents to the summary of the Doctree + if (fsitem.path().stem().string() == "index") + { + std::string infilestr = load_from_file (fsitem.path ()); + this->set_markdown_summary (infilestr); + } + // else it is a non-index file- + // create a Document and add it to the tree + else { + std::ifstream infile (fsitem.path ()); + std::shared_ptr doc + (new Document (infile)); + infile.close (); + + // file modified date from system + struct stat buf; + if (stat (fsitem.path().string().c_str(), &buf) == 0) + doc.get()->set_modified_date (buf.st_mtim.tv_sec); + + this->add_document (doc.get()); + } + } + } + } + catch (std::filesystem::filesystem_error) { + std::cout << NO_SUCH_PATH_ERROR << std::endl; + } + + // add the trees for the children recursively + for (DocumentTree &child : this->children) + child.document_tree_builder (srcpath_str + "/" + child.title); } }