Document tree generation to HTML output completed
[biaweb2.git] / biawebdocument.hpp
1 #ifndef __BIAWEB__
2 #define __BIAWEB__
3 #include <iostream>
4 #include <fstream>
5 #include <string>
6 #include <list>
7 #include <memory>
8 #include <ctime>
9 #include "biawebutil.hpp"
10 #include "biawebsidebar.hpp"
11
12 // "discount" markdown library is a C library and hence requires to be wrapped in
13 // extern "C"
14 extern "C" {
15 #include <mkdio.h>
16 }
17 // class to represent a biaweb document which can have a file name, title, description,
18 // keywords, content and sidebar items
19 namespace biaweb {
20 class Document
21 {
22 protected:
23 std::string filename;
24 std::string title;
25 std::string meta_desc;
26 std::string meta_keywords;
27 std::string content;
28 std::list<SideBar> sidebars;
29 std::time_t cdate;
30 std::time_t mdate;
31 bool is_index;
32
33 public:
34 Document (std::string title = "", std::string meta_desc = "",
35 std::string meta_keywords = "", std::string content = "",
36 bool is_index = false, std::time_t cdate= std::time(nullptr),
37 std::time_t mdate = std::time(nullptr))
38 {
39 this->title = title;
40 this->meta_desc = meta_desc;
41 this->meta_keywords = meta_keywords;
42 this->content = content;
43 this->is_index = is_index;
44 if (! is_index)
45 this->filename = convert_title (title);
46 else
47 this->filename = "index";
48 this->cdate = cdate;
49 this->mdate = mdate;
50 }
51
52 // set whether this is the index document
53 void set_index (bool index = true) {
54 this->is_index = index;
55 index == true ? this->filename = "index" :
56 this->filename = convert_title (this->title);
57 }
58
59 // get whether this is the index document
60 bool get_index () {
61 return this->is_index;
62 }
63
64 // get the file name
65 std::string get_filename () {
66 return this->filename;
67 }
68
69 // set the document modification date
70 void set_modified_date (std::time_t modif) {
71 this->mdate = modif;
72 }
73
74 // get the document modification date
75 std::time_t get_modified_date () {
76 return this->mdate;
77 }
78
79 // set the document creation date
80 void set_creation_date (std::time_t creat) {
81 this->cdate = creat;
82 }
83
84 // get the document creation date
85 std::time_t get_creation_date () {
86 return this->cdate;
87 }
88
89 // output the document to HTML using the template
90 void output_to_html (std::string path);
91
92 // set the content portion of document as raw HTML content
93 void set_content (std::string content) {
94 this->content = content;
95 }
96
97 // read the contents of marked marked-up content string "str" into the
98 // contents after converting to HTML.
99 void set_markdown_content (std::string str);
100
101 void set_meta_keywords(std::string meta_keywords) {
102 this->meta_keywords = meta_keywords;
103 }
104
105 void set_meta_desc(std::string meta_desc) {
106 this->meta_desc = meta_desc;
107 }
108
109 void set_title(std::string title) {
110 this->title = title;
111 if (this->is_index)
112 this->filename = "index";
113 else
114 this->filename = convert_title (title);
115 }
116
117 std::string get_content () {
118 return this->content;
119 }
120
121 std::string get_meta_keywords() {
122 return this->meta_keywords;
123 }
124
125 std::string get_meta_desc() {
126 return this->meta_desc;
127 }
128
129 std::string get_title() {
130 return this->title;
131 }
132
133 void add_side_bar (SideBar bar) {
134 sidebars.insert (sidebars.cend(), bar);
135 }
136 };
137
138 void Document::set_markdown_content (std::string str) {
139 // discount is a C library and it doesn't work well with C++ streams
140 // and there seems no way to get the output of any of these functions
141 // into an std::string.
142 // the only option seems to be to write the output of the markdown()
143 // function to a temporary working file and then read it back into C++
144 // with the normal std::ifstream and feed it into the std::string
145 // till a cleaner solution can be found.
146 MMIOT *doc;
147 doc = mkd_string (str.c_str(), str.size(), 0);
148 FILE *f = fopen (".biaweb.tmp", "w");
149 markdown (doc, f, 0);
150 fclose (f);
151 std::ifstream ftmp (".biaweb.tmp");
152 std::string tmpl ( (std::istreambuf_iterator<char> (ftmp)),
153 (std::istreambuf_iterator<char> ())
154 );
155
156 while (! ftmp.eof ())
157 {
158 std::string line;
159 ftmp >> line;
160 tmpl.append (line);
161 tmpl.append (" ");
162 }
163 ftmp.close ();
164 remove (".biaweb.tmp");
165 this->content.append (tmpl);
166 mkd_cleanup (doc);
167 }
168
169 void Document::output_to_html (std::string path)
170 {
171 std::ifstream tpl;
172 tpl.open ("templates/main.tpl.html", std::ios_base::openmode::_S_in);
173 std::string main_tpl ( (std::istreambuf_iterator<char> (tpl)),
174 (std::istreambuf_iterator<char> ()) );
175 tpl.close ();
176 // first render the sidebars
177 std::string sidebartext;
178 for (SideBar bar : sidebars) {
179 sidebartext += bar.to_html ();
180 }
181
182 char ctm_str[100], mtm_str[100];
183 std::time_t creat = this->cdate;
184 std::time_t modif = this->cdate;
185 std::strftime (ctm_str, sizeof (ctm_str),
186 "%d %b %Y, %H:%M", std::localtime (&creat));
187 std::strftime (mtm_str, sizeof (mtm_str),
188 "%d %b %Y, %H:%M", std::localtime (&modif));
189
190 // Allocate enough space for the output buffer
191 std::unique_ptr<char[]> final_templ(
192 new char[main_tpl.size()+
193 this->title.size()+
194 this->content.size() +
195 this->meta_desc.size() +
196 this->meta_keywords.size () +
197 200 +
198 sidebartext.size()]);
199 std::sprintf (final_templ.get (), main_tpl.c_str(), this->title.c_str(),
200 ctm_str, mtm_str,
201 this->content.c_str(), sidebartext.c_str());
202
203 std::ofstream f (path + "/" + this->filename + ".html");
204 f << final_templ.get ();
205 f.close ();
206 }
207 }
208
209 #endif