Readme.md - added Section for customization and notes
[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 <iomanip>
9 #include <ctime>
10 #include <fmt/format.h>
11 #include "biawebutil.hpp"
12 #include "biawebsidebar.hpp"
13 #include "biawebstrings.hpp"
14 #include "biawebnavigationbit.hpp"
15 #include "biawebtemplate.hpp"
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 NavigationBit navbit;
30 std::time_t cdate;
31 std::time_t mdate;
32 bool is_index;
33
34 public:
35 Document (std::string title = "", std::string meta_desc = "",
36 std::string meta_keywords = "", std::string content = "",
37 bool is_index = false, std::time_t cdate= std::time(nullptr),
38 std::time_t mdate = std::time(nullptr))
39 {
40 this->title = escape_html (title);
41 this->meta_desc = escape_html (meta_desc);
42 this->meta_keywords = escape_html (meta_keywords);
43 this->content = content;
44 this->is_index = is_index;
45 if (! is_index)
46 this->filename = convert_title (title);
47 else
48 this->filename = "index";
49 this->cdate = cdate;
50 this->mdate = mdate;
51 }
52
53 // Constructor to parse the document from a stream instead of manually creating it
54 // File should be of the format
55 // first line: title
56 // second line: Description
57 // third line: Keywords
58 // fourth line: (creation date) YYYY-MM-DD HH:II TZ format
59 // fourth line onwards: Markdown contents
60 Document (std::istream &file) ;
61
62 // set the navigation bit
63 void set_navigation_bit (NavigationBit navbit) {
64 this->navbit = navbit;
65 }
66
67 // set whether this is the index document
68 void set_index (bool index = true) {
69 this->is_index = index;
70 index == true ? this->filename = "index" :
71 this->filename = convert_title (this->title);
72 }
73
74 // get whether this is the index document
75 bool get_index () {
76 return this->is_index;
77 }
78
79 // get the file name
80 std::string get_filename () {
81 return this->filename;
82 }
83
84 // set the document modification date
85 void set_modified_date (std::time_t modif) {
86 this->mdate = modif;
87 }
88
89 // get the document modification date
90 std::time_t get_modified_date () {
91 return this->mdate;
92 }
93
94 // set the document creation date
95 void set_creation_date (std::time_t creat) {
96 this->cdate = creat;
97 }
98
99 // get the document creation date
100 std::time_t get_creation_date () {
101 return this->cdate;
102 }
103
104 // output the document to HTML using the template specified
105 void output_to_html (Template *t, std::string path);
106
107 // set the content portion of document as raw HTML content
108 void set_content (std::string content) {
109 this->content = content;
110 }
111
112 // read the contents of marked marked-up content string "str" into the
113 // contents after converting to HTML.
114 void set_markdown_content (std::string str);
115
116 void set_meta_keywords(std::string meta_keywords) {
117 this->meta_keywords = escape_html (meta_keywords);
118 }
119
120 void set_meta_desc(std::string meta_desc) {
121 this->meta_desc = escape_html (meta_desc);
122 }
123
124 void set_title(std::string title) {
125 this->title = title;
126 if (this->is_index)
127 this->filename = "index";
128 else
129 this->filename = convert_title (title);
130 }
131
132 std::string get_content () {
133 return this->content;
134 }
135
136 std::string get_meta_keywords() {
137 return this->meta_keywords;
138 }
139
140 std::string get_meta_desc() {
141 return this->meta_desc;
142 }
143
144 std::string get_title() {
145 return this->title;
146 }
147
148 void add_side_bar (SideBar bar) {
149 sidebars.insert (sidebars.cend(), bar);
150 }
151 };
152
153 // Parse and construct a document from a stream instead of individual fields
154 Document::Document (std::istream &infile) {
155 infile.seekg (0);
156 // parse the title, description, keywords, creation time and and contents
157 std::string title, description, keywords, creattime, contents;
158 // read the title
159 std::getline (infile, title);
160 if (infile.eof ()) return;
161 this->title = escape_html (title);
162 this->filename = convert_title (title);
163 // read description
164 std::getline (infile, description);
165 if (infile.eof ()) return;
166 this->meta_desc = escape_html (description);
167 // read the keywords
168 std::getline (infile, keywords);
169 if (infile.eof ()) return;
170 this->meta_keywords = escape_html (keywords);
171 // read the creation date/time and also set the modification time
172 // to creation date/time by default
173 std::getline (infile, creattime);
174 if (infile.eof ()) return;
175 std::stringstream s (creattime);
176 std::tm t;
177 s >> std::get_time (&t, DATE_IN_FORMAT);
178 if (s.fail ())
179 std::cout << WARNING_PARSE_FAILED << this->filename << "\n";
180
181 this->cdate = mktime (&t);
182 this->mdate = this->cdate;
183 // read the rest of contents
184 std::string line;
185 while (! infile.eof ()) {
186 std::getline (infile, line);
187 contents.append (line + "\n");
188 }
189 this->set_markdown_content (contents);
190 }
191
192 void Document::set_markdown_content (std::string str) {
193 this->content = convert_to_markdown (str);
194 }
195
196 // output the document using the provided template
197 void Document::output_to_html (Template *t, std::string path)
198 {
199 std::string templstr = t->get_main_tpl ();
200
201 // read the style template file
202 std::string stylesheet = t->get_style_tpl ();
203 // first render the sidebars
204 std::string sidebartext;
205 for (SideBar bar : sidebars) {
206 sidebartext += bar.to_html (t);
207 }
208
209 // render the navigation bit
210 std::string navbit_str = this->navbit.to_html (t);
211
212 // time of creation and modification
213 struct std::tm c, m;
214 c = *std::localtime (&this->cdate);
215 m = *std::localtime (&this->mdate);
216
217 // format the template with the values
218 std::string outputhtml = fmt::format (templstr,
219 fmt::arg ("title", this->title),
220 fmt::arg ("keywords", this->meta_keywords),
221 fmt::arg ("stylesheet", stylesheet),
222 fmt::arg ("description", this->meta_desc),
223 fmt::arg ("cdate", c),
224 fmt::arg ("mdate", m),
225 fmt::arg ("navbit", navbit_str),
226 fmt::arg ("contents", this->content),
227 fmt::arg ("sidebar", sidebartext)
228 );
229
230 std::ofstream f (path + "/" + this->filename + ".html");
231 f << outputhtml;
232 f.close ();
233 }
234 }
235
236 #endif