stamdStatic 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> 8 9 #include "indexer.hpp" 10 11 #include <hemplate/atom.hpp> 12 #include <hemplate/html.hpp> 13 #include <hemplate/rss.hpp> 14 #include <hemplate/sitemap.hpp> 15 16 #include "article.hpp" 17 18 namespace 19 { 20 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 } 28 29 } // namespace 30 31 namespace stamd 32 { 33 34 void Indexer::add(const article_s& article) 35 { 36 m_articles.emplace_back(article); 37 } 38 39 void Indexer::add(categories_t categories) 40 { 41 m_categories.merge(categories); 42 } 43 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 } 55 56 void Indexer::create_index(std::ostream& ost, const std::string& doc_title) 57 { 58 using namespace hemplate::html; // NOLINT 59 60 const Article index(doc_title, m_options, m_categories); 61 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 } 76 77 return li { 78 span {article->get_date(), " - "}, 79 aHref {article->get_filename(), article->get_title()}, 80 }; 81 } 82 ), 83 }, 84 }; 85 } 86 ); 87 } 88 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; 93 94 const std::string& base_url = m_options.base_url; 95 const std::string& author_name = m_options.author; 96 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) 110 { 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); 116 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 }; 124 } 125 ), 126 }, 127 }; 128 } 129 130 void Indexer::create_rss(std::ostream& ost, const std::string& doc_title) const 131 { 132 using namespace hemplate::rss; // NOLINT 133 using hemplate::rss::link; 134 135 const std::string& base_url = m_options.base_url; 136 const std::string& desc = m_options.description; 137 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) 151 { 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); 158 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 }; 166 } 167 ), 168 }, 169 }, 170 }; 171 } 172 173 void Indexer::create_sitemap(std::ostream& ost) const 174 { 175 using namespace hemplate::sitemap; // NOLINT 176 177 static const std::string& base_url = m_options.base_url; 178 179 ost << element { 180 xml {}, 181 urlset { 182 transform( 183 m_articles, 184 [&](const auto& article) 185 { 186 const auto& filename = article->get_filename(); 187 const auto& date = article->get_date(); 188 189 return url { 190 loc {base_url + filename}, 191 lastmod {date}, 192 }; 193 } 194 ), 195 } 196 }; 197 } 198 199 void Indexer::create_robots(std::ostream& ost) const 200 { 201 static const std::string& base_url = m_options.base_url; 202 203 ost << "User-agent: *"; 204 ost << std::format("Sitemap: {}/sitemap.xml", base_url); 205 } 206 207 } // namespace stamd