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