stamd

Static Markdown Page Generator
git clone git://git.dimitrijedobrota.com/stamd.git
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING

indexer.cpp (5316B)


0 #include <algorithm>
1 #include <ctime>
2 #include <format>
3 #include <iomanip>
4 #include <iterator>
5 #include <ostream>
6 #include <sstream>
7 #include <string>
9 #include "indexer.hpp"
11 #include <hemplate/atom.hpp>
12 #include <hemplate/html.hpp>
13 #include <hemplate/rss.hpp>
14 #include <hemplate/sitemap.hpp>
16 #include "article.hpp"
18 namespace
19 {
21 int64_t parse_time(const std::string& date)
22 {
23 std::tm tms = {};
24 std::stringstream stream(date);
25 stream >> std::get_time(&tms, "%Y-%m-%d");
26 return std::mktime(&tms);
27 }
29 } // namespace
31 namespace stamd
32 {
34 void Indexer::add(const article_s& article)
35 {
36 m_articles.emplace_back(article);
37 }
39 void Indexer::add(categories_t categories)
40 {
41 m_categories.merge(categories);
42 }
44 void Indexer::sort()
45 {
46 std::sort(
47 begin(m_articles),
48 end(m_articles),
49 [](const auto& lft, const auto& rht)
50 {
51 return lft->get_date() > rht->get_date();
52 }
53 );
54 }
56 void Indexer::create_index(std::ostream& ost, const std::string& doc_title)
57 {
58 using namespace hemplate::html; // NOLINT
60 const Article index(doc_title, m_options, m_categories);
62 ost << index.write(
63 [&]
64 {
65 return element {
66 h1 {doc_title},
67 ul {
68 {{"class", "index"}},
69 transform(
70 m_articles,
71 [](const auto& article) -> element
72 {
73 if (article->is_hidden()) {
74 return {};
75 }
77 return li {
78 span {article->get_date(), " -&nbsp"},
79 aHref {article->get_filename(), article->get_title()},
80 };
81 }
82 ),
83 },
84 };
85 }
86 );
87 }
89 void Indexer::create_atom(std::ostream& ost, const std::string& doc_title) const
90 {
91 using namespace hemplate::atom; // NOLINT
92 using hemplate::atom::link;
94 const std::string& base_url = m_options.base_url;
95 const std::string& author_name = m_options.author;
97 ost << element {
98 xml {},
99 feed {},
100 title {doc_title},
101 id {base_url},
102 updated {format_time_now()},
103 author {name {author_name}},
104 linkSelf {base_url + "/atom.xml"},
105 linkAlternate {base_url + "blog/atom.xml"},
106 feed {
107 transform(
108 m_articles,
109 [&](const auto& article)
111 const auto filename = article->get_filename();
112 const auto art_title = article->get_title();
113 const auto date = article->get_date();
114 const auto art_summary =
115 article->get("summary").value_or(m_options.summary);
117 return entry {
118 title {art_title},
119 id {base_url + filename},
120 linkHref {base_url + filename},
121 updated {format_time(parse_time((date)))},
122 summary {art_summary},
123 };
125 ),
126 },
127 };
130 void Indexer::create_rss(std::ostream& ost, const std::string& doc_title) const
132 using namespace hemplate::rss; // NOLINT
133 using hemplate::rss::link;
135 const std::string& base_url = m_options.base_url;
136 const std::string& desc = m_options.description;
138 ost << element {
139 xml {},
140 rss {
141 channel {
142 title {doc_title},
143 link {base_url},
144 description {desc},
145 generator {"stamd"},
146 language {"en-us"},
147 atomLink {base_url + "blog/rss.xml"},
148 transform(
149 m_articles,
150 [&](const auto& article)
152 const auto filename = article->get_filename();
153 const auto date = article->get_date();
154 const auto author_name =
155 article->get("author").value_or(m_options.author);
156 const auto email =
157 article->get("email").value_or(m_options.email);
159 return item {
160 title {filename},
161 link {base_url + filename},
162 guid {base_url + filename},
163 pubDate {format_time(parse_time(date))},
164 author {std::format("{} ({})", email, author_name)},
165 };
167 ),
168 },
169 },
170 };
173 void Indexer::create_sitemap(std::ostream& ost) const
175 using namespace hemplate::sitemap; // NOLINT
177 static const std::string& base_url = m_options.base_url;
179 ost << element {
180 xml {},
181 urlset {
182 transform(
183 m_articles,
184 [&](const auto& article)
186 const auto& filename = article->get_filename();
187 const auto& date = article->get_date();
189 return url {
190 loc {base_url + filename},
191 lastmod {date},
192 };
194 ),
196 };
199 void Indexer::create_robots(std::ostream& ost) const
201 static const std::string& base_url = m_options.base_url;
203 ost << "User-agent: *";
204 ost << std::format("Sitemap: {}/sitemap.xml", base_url);
207 } // namespace stamd