stamd

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

article.cpp (4647B)


      1 #include <format>
      2 #include <iostream>
      3 #include <numeric>
      4 
      5 #include "article.hpp"
      6 
      7 #include <hemplate/attribute.hpp>
      8 #include <hemplate/classes.hpp>
      9 
     10 #include "utility.hpp"
     11 
     12 namespace stamd {
     13 
     14 std::optional<std::string> article::get(const std::string& key) const
     15 {
     16   const auto itr = m_symbols.find(key);
     17   if (itr == end(m_symbols))
     18   {
     19     // std::cerr << "Warning: getting invalid value for: " << key << std::endl;
     20     return {};
     21   }
     22   return itr->second;
     23 }
     24 
     25 std::string article::get_filename() const
     26 {
     27   return m_symbols.find("filename")->second;
     28 }
     29 
     30 std::string article::get_date() const
     31 {
     32   return get("date").value_or("0000-00-00");
     33 }
     34 
     35 std::string article::get_title() const
     36 {
     37   return get("title").value_or(get_filename());
     38 }
     39 
     40 std::string article::get_language() const
     41 {
     42   return get("language").value_or("en");
     43 }
     44 
     45 void article::print_nav(std::ostream& ost)
     46 {
     47   using namespace hemplate;  // NOLINT
     48 
     49   static const char* base = "https://dimitrijedobrota.com/blog";
     50 
     51   ost << html::nav()
     52              .add(html::a("&lt;-- back", {{"class", "back"}}))
     53              .add(html::a("index", {{"href", base}}))
     54              .add(html::a("home --&gt;", {{"href", "/"}}));
     55 }
     56 
     57 void article::print_categories(std::ostream& ost,
     58                                const categories_t& categories)
     59 {
     60   using namespace hemplate;  // NOLINT
     61 
     62   ost << html::nav().set("class", "categories");
     63   ost << html::h3("Categories: ");
     64   ost << html::p();
     65   for (const auto& category : categories)
     66   {
     67     auto ctgry = category;
     68     normalize(ctgry);
     69     ost << html::a(category, {{"href", std::format("./{}.html", ctgry)}});
     70   }
     71   ost << html::p();
     72   ost << html::nav();
     73 }
     74 
     75 void article::write_header(std::ostream& ost) const
     76 {
     77   using namespace hemplate;  // NOLINT
     78 
     79   static const char* description_s =
     80       "Dimitrije Dobrota's personal site. You can find my daily "
     81       "findings in a "
     82       "form of articles on my blog as well as various programming "
     83       "projects.";
     84 
     85   static const attributeList icon  = {{"rel", "icon"}, {"type", "image/png"}};
     86   static const attributeList style = {{"rel", "stylesheet"},
     87                                       {"type", "text/css"}};
     88 
     89   static const attributeList viewport = {
     90       {"content", "width=device-width, initial-scale=1"},
     91       {"name", "viewport"}};
     92 
     93   static const attributeList description = {{"name", "description"},
     94                                             {"content", description_s}};
     95 
     96   static const attributeList rss = {{"rel", "alternate"},
     97                                     {"type", "application/atom+xml"},
     98                                     {"title", "RSS feed"},
     99                                     {"href", "/blog/rss.xml"}};
    100 
    101   static const attributeList atom = {{"rel", "alternate"},
    102                                      {"type", "application/atom+xml"},
    103                                      {"title", "Atom feed"},
    104                                      {"href", "/blog/atom.xml"}};
    105 
    106   ost << html::doctype();
    107   ost << html::html().set("lang", get_language());
    108   ost << html::head()
    109              .add(html::title(get_title()))
    110              .add(html::meta(viewport))
    111              .add(html::meta({{"charset", "UTF-8"}}))
    112              .add(html::meta(description))
    113              .add(html::link(style).set("href", "/css/index.css"))
    114              .add(html::link(style).set("href", "/css/colors.css"))
    115              .add(html::link(rss))
    116              .add(html::link(atom))
    117              .add(html::link(icon)
    118                       .set("sizes", "32x32")
    119                       .set("href", "/img/favicon-32x32.png"))
    120              .add(html::link(icon)
    121                       .set("sizes", "16x16")
    122                       .set("href", "/img/favicon-16x16.png"));
    123 
    124   ost << html::body();
    125   ost << html::input()
    126              .set("type", "checkbox")
    127              .set("id", "theme_switch")
    128              .set("class", "theme_switch");
    129 
    130   ost << html::div().set("id", "content");
    131 
    132   if (!m_nonav)
    133   {
    134     ost << html::header();
    135     print_nav(ost);
    136     ost << html::hr();
    137     ost << html::header();
    138   }
    139 
    140   ost << html::main();
    141   ost << html::label(" ")
    142              .set("for", "theme_switch")
    143              .set("class", "switch_label");
    144 
    145   if (!m_categories.empty()) print_categories(ost, m_categories);
    146 }
    147 
    148 void article::write_footer(std::ostream& ost) const
    149 {
    150   using namespace hemplate;  // NOLINT
    151 
    152   ost << html::main();
    153 
    154   if (!m_nonav)
    155   {
    156     ost << html::footer();
    157     ost << html::hr();
    158     print_nav(ost);
    159     ost << html::footer();
    160   }
    161 
    162   ost << html::div();
    163   ost << html::script(" ").set("src", "/scripts/main.js");
    164   ost << html::body();
    165   ost << html::html();
    166 }
    167 
    168 }  // namespace stamd