-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathcssg.cpp
More file actions
165 lines (121 loc) · 4.69 KB
/
Copy pathcssg.cpp
File metadata and controls
165 lines (121 loc) · 4.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
#include <iostream>
#include <algorithm>
#include <map>
#include "str.h"
#include "file.h"
#include "parameter.h"
/* Information about a markdown file */
struct FileInfo {
std::map<std::string, std::string> values;
/* How big the head is */
int size{};
};
/* All tags that one can use in their markdown file */
const std::vector<std::string> available_tags = {
"name",
"description",
"author"
};
FileInfo *get_head(const std::string content) {
auto *file_info = new FileInfo();
int i = 0;
int ctx = 0;
char c;
std::string line = "";
file_info->size = 0;
while ((c = content[i++]) != 0) {
file_info->size++;
if (c != '\n') {
line += c;
continue;
}
if (line == "---") {
if (ctx == 0) {
ctx = 1;
line = "";
continue;
}
break;
}
// We're in a context where the head is defined
// This head looks like this
//
// name: niclas
// description: ...
// ...
if (ctx)
for (const auto &item: available_tags)
if (line.starts_with(item))
file_info->values[item] = str_trim(line.substr(item.length() + 1, line.length()));
line = "";
}
return file_info;
}
std::string generate_html_header(FileInfo *i) {
std::string result;
result.append("<meta name=\"description\" content=\"" + i->values["description"] + "\">\n");
result.append("<title>" + i->values["name"] + "</title>");
// For Social-Media (Discord, Skype, Twitter etc.)
result.append("<meta property=\"og:title\" content=\"" + i->values["name"] + "\" />\n");
result.append("<meta property=\"og:description\" content=\"" + i->values["description"] + "\" />\n");
result.append("<meta name=\"theme-color\" content=\"#FF0000\">\n");
result.append("<meta property=\"og:type\" content=\"website\" />\n");
return result;
}
std::string generate_html(FileInfo *i, std::string &content, std::string template_content) {
content = content.substr(i->size, content.length());
for (const auto &item: i->values)
template_content = replaceAll(template_content, "{{" + item.first + "}}", item.second);
template_content = replaceAll(template_content, "{{content}}", content);
template_content = replaceAll(template_content, "{{head}}", generate_html_header(i));
return template_content;
}
void debug_log(std::string path, FileInfo *i) {
std::cout << "path: " << path << std::endl;
for (const auto &item: i->values)
std::cout << (item.first + ": " + item.second) << std::endl;
std::cout << "---" << std::endl;
}
std::string get_html_file_name(FileInfo *fileInfo) {
std::string file_name = replaceAll(fileInfo->values["name"], " ", "-") + ".html";
std::transform(file_name.begin(), file_name.end(), file_name.begin(), ::tolower);
return file_name;
}
void process_file(std::string &template_path, std::string &file_path) {
std::string file_content = read_file(file_path);
std::string template_content = read_file(template_path);
FileInfo *file_info = get_head(file_content);
std::string file_name = get_html_file_name(file_info);
write_file("./out/posts/" + file_name, generate_html(file_info, file_content, template_content));
debug_log(file_path, file_info);
}
int main(__attribute__((unused)) int argc, char **argv) {
auto p = parse_argv(argv);
auto input = p["input"];
auto postTemplate = p["post-template"];
auto indexTemplate = p["index-template"];
auto posts = get_files_in_directory(input);
// Creating the out directory
create_directory("out", true);
create_directory("out/posts");
if (is_directory(input))
for (std::string value: posts)
process_file(postTemplate, value);
else process_file(postTemplate, input);
/* Creates an index file, containing all posts */
if (p.contains("index-template")) {
std::string index_content = read_file(indexTemplate);
std::string list_string = "";
std::for_each(posts.begin(), posts.end(), [&list_string](std::string &value) {
std::string file_content = read_file(value);
FileInfo *file_info = get_head(file_content);
list_string +=
"<li><a href=\"posts/" + get_html_file_name(file_info) + "\">" + file_info->values["name"] +
"</a></li> \n";
});
index_content = replaceAll(index_content, "{{items}}", list_string);
write_file("out/index.html", index_content);
}
std::cout << "Successfully generated the pages." << std::endl;
return 0;
}