Changed the rendering code for templating output
authorHarishankar <v.harishankar@gmail.com>
Tue, 19 May 2020 14:47:38 +0000 (20:17 +0530)
committerHarishankar <v.harishankar@gmail.com>
Tue, 19 May 2020 14:47:38 +0000 (20:17 +0530)
Changed from the C sprintf to using library libfmt::format in C++
to use named parameters in the template. NOTE: This means the
template file cannot contain any { or } other than the template
variables otherwise it screws up. So moved the CSS stylesheet to its
own template

13 files changed:
CMakeLists.txt
biawebdoclist.hpp
biawebdocument.hpp
biawebdocumenttree.hpp
biawebsidebar.hpp
biawebstrings.hpp
templates/doclist.tpl.html
templates/doclistitem.tpl.html
templates/main.tpl.html
templates/sidebar.tpl.html
templates/sidebaritem.tpl.html
templates/sidebarlinkitem.tpl.html
templates/style.tpl.css [new file with mode: 0644]

index cc14265..47c11a9 100644 (file)
@@ -2,5 +2,5 @@ cmake_minimum_required (VERSION 3.0)
 project (biaweb2 CXX)
 set (CMAKE_CXX_STANDARD 17)
 add_executable (biaweb biaweb.cpp)
-target_link_libraries (biaweb markdown)
+target_link_libraries (biaweb markdown fmt)
 
index 6082b39..7c4efcd 100644 (file)
@@ -4,7 +4,10 @@
 #include <string>
 #include <fstream>
 #include <iostream>
+#include <iomanip>
 #include <list>
+#include <fmt/format.h>
+#include <fmt/chrono.h>
 #include "biawebstrings.hpp"
 #include "biawebdocument.hpp"
 
@@ -21,7 +24,7 @@ namespace biaweb {
       public:
         DocListItem (std::string title, std::string url, 
                     std::time_t ctime, std::time_t mtime ) {
-            this->title = title;
+            this->title = escape_html (title);
             this->url = url;
             this->ctime = ctime; 
             this->mtime = mtime;
@@ -52,10 +55,10 @@ namespace biaweb {
             return this->title;
         }
         void set_title(std::string title) {
-            this->title = title;
+            this->title = escape_html (title);
         }
         
-        // output to HTML
+        // output to HTML vide the template
         std::string to_html (std::string templatedir);
     };
     
@@ -66,24 +69,11 @@ namespace biaweb {
                             (std::istreambuf_iterator<char> ()) );
         templ.close ();
         
-        // Allocate enough size for the output buffer
-        std::unique_ptr<char[]> outputstr (new char [templstr.size() +
-                                                     this->title.size() +
-                                                     this->url.size () +
-                                                     200]);
+        std::string outputhtml = fmt::format (templstr, fmt::arg("url", this->url),
+                               fmt::arg("doctitle", this->title), 
+                               fmt::arg("cdate", *std::localtime (&this->ctime)),
+                               fmt::arg("mdate", *std::localtime (&this->mtime)));
         
-        char ctm_str[100];
-        char mtm_str[100];
-        strftime (ctm_str, 100, DATE_FORMAT, std::localtime (&this->ctime));
-        strftime (mtm_str, 100, DATE_FORMAT, std::localtime (&this->mtime));
-
-        sprintf (outputstr.get(), templstr.c_str(), 
-                            this->url.c_str(),
-                            this->title.c_str(),
-                            ctm_str, mtm_str);
-        
-        std::string outputhtml; 
-        outputhtml.append (outputstr.get());
         return outputhtml;
     }
 
@@ -94,7 +84,7 @@ namespace biaweb {
         std::list<DocListItem> items;
       public:
         void set_title (std::string title) {
-            this->title = title;
+            this->title = escape_html (title);
         }
         // add a document item
         void add_document_item (DocListItem docitem) {
@@ -109,24 +99,18 @@ namespace biaweb {
         std::string templstr ( (std::istreambuf_iterator<char> (templ) ),
                                 (std::istreambuf_iterator<char> ()));
 
-        std::string docitems = "";
+        templ.close ();
+
         std::string outputhtml = "";
         // if the number of elements is non zero
         if (this->items.size () != 0) {
+            std::string docitems = "";
             for (DocListItem item : this->items)
                 docitems += item.to_html (templatedir);
-            
-            // Allocate space for output buffer
-            std::unique_ptr<char[]> outputstr (new char [ 
-                                                templstr.size () +
-                                                docitems.size () +
-                                                this->title.size ()
-                                                   ]);
-            sprintf (outputstr.get(), templstr.c_str(), 
-                        this->title.c_str(),
-                        docitems.c_str() );
-            
-            outputhtml.append (outputstr.get());
+
+            outputhtml = fmt::format (templstr, 
+                                            fmt::arg ("title", this->title),
+                                            fmt::arg ("docitems", docitems));
         }
         return outputhtml;
     }
index 9829bcd..40b0207 100644 (file)
@@ -5,7 +5,10 @@
 #include <string>
 #include <list>
 #include <memory>
+#include <iomanip>
 #include <ctime>
+#include <fmt/format.h>
+#include <fmt/chrono.h>
 #include "biawebutil.hpp"
 #include "biawebsidebar.hpp"
 #include "biawebstrings.hpp"
@@ -32,9 +35,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)
@@ -95,11 +98,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) {
@@ -137,41 +140,33 @@ namespace biaweb {
     
     void Document::output_to_html (std::string templatedir, std::string path)
     {
-        std::ifstream tpl;
-        tpl.open (templatedir + "/main.tpl.html");
-        std::string main_tpl ( (std::istreambuf_iterator<char> (tpl)),
+        std::ifstream tpl (templatedir + "/main.tpl.html");
+        std::string templstr ( (std::istreambuf_iterator<char> (tpl)),
                                 (std::istreambuf_iterator<char> ()) );
         tpl.close ();
+        std::ifstream style (templatedir + "/style.tpl.css");
+        std::string stylesheet ( (std::istreambuf_iterator<char> (style)),
+                                (std::istreambuf_iterator<char> ()));
+        style.close ();
         // 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());
+        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", *std::localtime (&this->cdate)),
+                                    fmt::arg ("mdate", *std::localtime (&this->mdate)),
+                                    fmt::arg ("contents", this->content),
+                                    fmt::arg ("sidebar", sidebartext)
+                                    );
 
         std::ofstream f (path + "/" + this->filename + ".html");
-        f << final_templ.get ();
+        f << outputhtml;
         f.close ();
     }
 }
index 7c44634..66dcd9f 100644 (file)
@@ -39,7 +39,7 @@ namespace biaweb {
 
         // 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;
@@ -74,7 +74,7 @@ namespace biaweb {
 
         // 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);
index 4aef44f..932aa2c 100644 (file)
@@ -4,6 +4,7 @@
 #include <list>
 #include <iostream>
 #include <fstream>
+#include <fmt/format.h>
 #include "biawebutil.hpp"
 
 // classes to describe the a list of items and sidebar item containers which form part of 
@@ -21,20 +22,20 @@ namespace biaweb {
             return this->sidebar_text;
         }
         void set_sidebar_text (std::string text) {
-            this->sidebar_text = text;
+            this->sidebar_text = escape_html (text);
         }
         std::string get_sidebar_url () {
             return this->sidebar_url;
         }
         void set_sidebar_url (std::string url) {
-            this->sidebar_url = url;
+            this->sidebar_url = escape_html (url);
         }
         // 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;
-            this->sidebar_url = url;
+            this->sidebar_text = escape_html (text);
+            this->sidebar_url = escape_html (url);
         }
     };
 
@@ -48,13 +49,9 @@ namespace biaweb {
                 std::string tpl_linkitem_str ( (std::istreambuf_iterator<char> (tpl_linkitem)),
                                                 (std::istreambuf_iterator<char> ()));
                 tpl_linkitem.close ();
-                std::unique_ptr<char[]> linktxt (new char[tpl_linkitem_str.size() 
-                                                        + this->sidebar_text.size ()
-                                                        + this->sidebar_url.size ()] );
-                std::sprintf (linktxt.get(), tpl_linkitem_str.c_str (),
-                                             this->sidebar_url.c_str (),
-                                            this->sidebar_text.c_str ());
-                html.append (linktxt.get ());
+                html = fmt::format (tpl_linkitem_str, 
+                                        fmt::arg ("itemurl", this->sidebar_url),
+                                        fmt::arg ("itemtext", this->sidebar_text));
             }
             // no text or url - item is empty - so it should be blank
             else
@@ -67,10 +64,7 @@ namespace biaweb {
             std::string tpl_item_str ( (std::istreambuf_iterator<char> (tpl_item)),
                                         (std::istreambuf_iterator<char> ()));
             tpl_item.close ();
-            std::unique_ptr<char[]> txt (new char [tpl_item_str.size () +
-                                                    this->sidebar_text.size ()]);
-            std::sprintf (txt.get (), tpl_item_str.c_str(), this->sidebar_text.c_str());
-            html.append (txt.get ());
+            html = fmt::format (tpl_item_str, fmt::arg ("itemtext", this->sidebar_text) );
         } 
         return html;
     }
@@ -101,28 +95,19 @@ namespace biaweb {
         std::string sidetpl_str ( ( std::istreambuf_iterator<char> (sidetpl)) , 
                                        (std::istreambuf_iterator<char> ()));
         sidetpl.close ();
-        std::string listitem;
+        std::string listitems;
         // first get the sidebar items and render them to HTML
         for (SideBarItem item : this->items) {
-            listitem += item.to_html (templatedir);
+            listitems += item.to_html (templatedir);
         }
-
-        std::unique_ptr<char[]> tpl_final (new char[sidetpl_str.size() + 
-                                                this->sidebar_title.size () +
-                                                listitem.size () ]);
         
-        std::string html;
-        // if there are items, sidebar should be rendered
+        std::string html = "";
+        // if there are items, sidebar should be rendered otherwise not needed
         if (items.size () > 0)
-        {        
-            std::sprintf (tpl_final.get (), sidetpl_str.c_str(), 
-                                        this->sidebar_title.c_str(), listitem.c_str()) ;
-            html.append ( tpl_final.get ());
-        }
-        // no items in the sidebar, render as empty string (even if it has a heading)
-        // since heading becomes meaningless without items
-        else 
-            html = "";
+            html = fmt::format (sidetpl_str, 
+                                        fmt::arg ("title", this->sidebar_title),
+                                        fmt::arg ("items", listitems));
+
         return html; 
     }
 }
index 1e073f0..702e5a9 100644 (file)
@@ -8,7 +8,7 @@ namespace biaweb {
     const char* ART_LIST = "List of Articles";
     const char* INDEX = "Index Page";
     // DATE FORMAT
-    const char* DATE_FORMAT = "%d %b %Y, %H:%M";
+    const char* DATE_FORMAT = "%d %b %Y, %H:%M %Z";
 }
 
 #endif
index 54bf4d4..206c4ac 100644 (file)
@@ -1,4 +1,4 @@
-<h2>%s</h2>
+<h2>{title}</h2>
 <table style="width:100%;" >
     <thead style="font-weight:bold;">
         <tr>
@@ -8,6 +8,6 @@
         </tr>
     </thead>
     <tbody>
-        %s
+        {docitems}
     </tbody>
 </table>
\ No newline at end of file
index 4f16239..3a17d80 100644 (file)
@@ -1,5 +1,5 @@
 <tr>    
-    <td><a href="%s">%s</a></td>
-    <td>%s</td>
-    <td>%s</td>
+    <td><a href="{url}">{doctitle}</a></td>
+    <td>{cdate:%d %b %Y, %H:%M %Z}</td>
+    <td>{mdate:%d %b %Y, %H:%M %Z}</td>
 </tr>
\ No newline at end of file
index 0073bfc..804d24c 100644 (file)
@@ -1,73 +1,27 @@
 <!DOCTYPE html>
 <html lang="en">
 <head>
-<title>My Site - %s</title>
-<meta name="keywords" content="%s">
-<meta name="description" content="%s">
+<title>My Site - {title}</title>
+<meta name="keywords" content="{keywords}">
+<meta name="description" content="{description}">
 <!-- change base href to your site URL -->
 <base href="http://my.site">
 <style>
-    body {
-        background-color: whitesmoke;
-        font-family:Arial, Helvetica, sans-serif;
-        font-size: 0.9em;
-        margin: 0;
-        padding: 0;
-    }
-    h1, h2, h3, h4, h5, h6 {
-        font-family: Georgia, 'Times New Roman', Times, serif;
-    }
-    div#header {
-        width: 100%;
-        color: white;
-        background-color:#a1a0c0;
-        height: 50px;
-        float: left;
-    }
-    div#modification {
-        width: 100%;
-        color: darkslateblue;
-        font-size: 0.9em;
-        float:left;
-    }
-    div#footer {
-        width: 100%;
-        text-align: center;
-        background-color: #a1a0c0;
-        color: white;
-        float:left;
-    }
-    div#sidebar {
-        float :right;
-        background-color: darkslateblue;
-        color: white;
-        width: 30%;
-        padding: 1%;
-    }
-    div#sidebar a, div#sidebar a:visited {
-        color: white;
-    }
-
-    div#content {
-        width: 63%;
-        margin-right:1%;
-        margin-left: 1%;
-        float: left;
-    }
+{stylesheet}
 </style>
 </head>
 <body>
     <div id="header"></div>
     <div id="content">
-        <div id="modification">Created on: %s, last modified: %s</div>
-        %s
+        <div id="modification">Created on: {cdate:%d %b %Y, %H:%M %Z}, 
+            last modified: {mdate:%d %b %Y, %H:%M %Z}</div>
+        {contents}
     </div>
     <div id="sidebar">
-        %s
+        {sidebar}
     </div>
     <div id ="footer">
         My copyright
     </div>
-
 </body>
 </html>
index a2e7c05..b4356ff 100644 (file)
@@ -1,4 +1,4 @@
-<h2>%s</h2>
+<h2>{title}</h2>
 <ul>
-%s
+{items}
 </ul>
\ No newline at end of file
index c6209ee..9ce49c0 100644 (file)
@@ -1 +1 @@
-<li>%s</li>
\ No newline at end of file
+<li>{itemtext}</li>
\ No newline at end of file
index 07afc4b..ff74287 100644 (file)
@@ -1 +1 @@
-<li><a href="%s">%s</a></li>
\ No newline at end of file
+<li><a href="{itemurl}">{itemtext}</a></li>
\ No newline at end of file
diff --git a/templates/style.tpl.css b/templates/style.tpl.css
new file mode 100644 (file)
index 0000000..4cb611d
--- /dev/null
@@ -0,0 +1,47 @@
+body { 
+    background-color:white;
+    color: black;
+    font-family:Verdana, Geneva, Tahoma, sans-serif;
+    font-size: 0.9em;
+    margin: 0;
+    padding: 0;
+}      
+h1, h2, h3, h4, h5, h6 {
+    font-family: Georgia, 'Times New Roman', Times, serif;
+}
+div#header {
+    width: 100%;
+    color: white;
+    background-color:#a1a0c0;
+    height: 50px;
+    float: left;
+}
+div#modification {
+    width: 100%;
+    color: darkslateblue;
+    font-size: 0.9em;
+    float:left;
+}
+div#footer {
+    width: 100%;
+    text-align: center;
+    background-color: #a1a0c0;
+    color: white;
+    float:left;
+}
+div#sidebar {
+    float :right;
+    background-color: #f0f0f0;
+    color: black;
+    width: 30%;
+    padding: 1%;
+}
+
+div#content {
+    width: 63%;
+    margin-right:1%;
+    margin-left: 1%;
+    float: left;
+    line-height: 150%;
+    text-align: justify;
+}