stamd

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

article.cpp (4576B)


0 #include <format> 1 #include <iterator> 2 #include <numeric> 3 #include <optional> 4 #include <string> 5 6 #include "article.hpp" 7 8 #include <hemplate/attribute.hpp> 9 #include <hemplate/classes.hpp> 10 11 #include "utility.hpp" 12 13 namespace stamd 14 { 15 16 std::optional<std::string> Article::get(const std::string& key) const 17 { 18 const auto itr = m_symbols.find(key); 19 if (itr == end(m_symbols)) { 20 // std::cerr << "Warning: getting invalid value for: " << key << std::endl; 21 return {}; 22 } 23 return itr->second; 24 } 25 26 std::string Article::get_filename() const 27 { 28 return m_filename; 29 } 30 31 std::string Article::get_date() const 32 { 33 return get("date").value_or("0000-00-00"); 34 } 35 36 std::string Article::get_title() const 37 { 38 return get("title").value_or(get_filename()); 39 } 40 41 std::string Article::get_language() const 42 { 43 return get("language").value_or("en"); 44 } 45 46 std::string Article::get_desciprtion() const 47 { 48 return get("description").value_or(m_options.description); 49 } 50 51 std::string Article::get_author() const 52 { 53 return get("author").value_or(m_options.author); 54 } 55 56 std::string Article::get_keywords() const 57 { 58 static const auto concat = [](const categories_t& categories) 59 { 60 if (categories.empty()) { 61 return std::string(); 62 } 63 64 return std::accumulate( 65 std::next(std::begin(categories)), 66 std::end(categories), 67 *categories.begin(), 68 [](const auto& acc, const auto& str) 69 { 70 return acc + ", " + str; 71 } 72 ); 73 }; 74 75 return get("keywords").value_or(concat(m_categories)); 76 } 77 78 hemplate::element Article::print_nav(const std::string& base) 79 { 80 using namespace hemplate::html; // NOLINT 81 82 return nav { 83 a { 84 {{"class", "back"}}, 85 "&lt;-- back", 86 }, 87 a { 88 {{"href", base}}, 89 "index", 90 }, 91 a { 92 {{"href", "/"}}, 93 "home --&gt;", 94 }, 95 }; 96 } 97 98 hemplate::element Article::print_categories(const categories_t& categories) 99 { 100 using namespace hemplate::html; // NOLINT 101 102 return nav { 103 {{"class", "categories"}}, 104 h3 {"Categories: "}, 105 p { 106 transform( 107 categories, 108 [](const auto& category) 109 { 110 auto ctgry = category; 111 normalize(ctgry); 112 return aHref { 113 std::format("./{}.html", ctgry), 114 category, 115 }; 116 } 117 ), 118 }, 119 }; 120 } 121 122 hemplate::element Article::write(const content_t& content) const 123 { 124 using namespace hemplate::html; // NOLINT 125 126 return element { 127 doctype {}, 128 html { 129 {{"lang", get_language()}}, 130 head { 131 title {get_title()}, 132 133 metaUTF8 {}, 134 metaName {"author", get_author()}, 135 metaName {"description", get_desciprtion()}, 136 metaName {"keywords", get_keywords()}, 137 metaName {"viewport", "width=device-width, initial-scale=1"}, 138 139 linkStylesheet {"/css/index.css"}, 140 linkStylesheet {"/css/colors.css"}, 141 142 element { 143 linkRss {"RSS feed", "/blog/rss.xml"}, 144 linkAtom {"Atom feed", "/blog/atom.xml"}, 145 }, 146 147 // Icons 148 linkIcon {"32x32", "/img/favicon-32x32.png"}, 149 linkIcon {"16x16", "/img/favicon-16x16.png"}, 150 }, 151 body { 152 input {{ 153 {"type", "checkbox"}, 154 {"id", "theme_switch"}, 155 {"class", "theme_switch"}, 156 }}, 157 hemplate::html::div { 158 {{"id", "content"}}, 159 m_nonav ? element{} : [&] { 160 return header { 161 print_nav(m_options.base_url + "blog"), 162 hr{}, 163 }; 164 }(), 165 main { 166 label { 167 {{"for", "theme_switch"}, {"class", "switch_label"},}, 168 }, 169 m_categories.empty() ? element {} : [&]() { 170 return print_categories(m_categories); 171 }(), 172 content(), 173 }, 174 m_nonav ? element{} : [&] { 175 return footer { 176 hr{}, 177 print_nav(m_options.base_url + "blog"), 178 }; 179 }(), 180 }, 181 script {{{"set", "/scripts/main.js"}}}, 182 }, 183 }, 184 }; 185 } 186 187 } // namespace stamd