stamdStatic Markdown Page Generator |
git clone git://git.dimitrijedobrota.com/stamd.git |
Log | Files | Refs | README | LICENSE | HACKING | CONTRIBUTING | CODE_OF_CONDUCT | BUILDING | |
commit | 17873aadd3a230164ca22881e7bfb3c669d83f72 |
parent | 4b021f8ceab0565d655f5afecf4286cd18b63f42 |
author | Dimitrije Dobrota <mail@dimitrijedobrota.com> |
date | Wed, 26 Jun 2024 20:20:19 +0200 |
General document improvements
Diffstat:M | .clang-tidy | | | ++++++---- |
M | CMakeLists.txt | | | +++---------- |
M | source/article.cpp | | | ++++++++--- |
M | source/article.hpp | | | +++- |
M | source/index.cpp | | | ++++++++++++++++++++++++++++------------------------ |
M | source/index.hpp | | | ++- |
M | source/main.cpp | | | ++++++++++++++++++++++++++++++++----------- |
7 files changed, 82 insertions(+), 54 deletions(-)
diff --git a/.clang-tidy b/.clang-tidy
@@ -9,17 +9,19 @@ Checks: "*,\
-*-braces-around-statements,\
-bugprone-argument-comment,\
-bugprone-easily-swappable-parameters,\
-concurrency-mt-unsafe,\
-cppcoreguidelines-avoid-magic-numbers,\
-fuchsia-multiple-inheritance,\
-hicpp-signed-bitwise,\
-llvm-header-guard,\
-llvm-include-order,\
-misc-no-recursion,\
-misc-non-private-member-variables-in-classes,\
-modernize-use-nodiscard,\
-modernize-use-trailing-return-type,\
-readability-function-cognitive-complexity,\
-readability-magic-numbers,\
fuchsia-multiple-inheritance,\
-misc-no-recursion,\
-misc-non-private-member-variables-in-classes"
-readability-magic-numbers
"
WarningsAsErrors: ''
CheckOptions:
- key: 'bugprone-argument-comment.StrictMode'
diff --git a/CMakeLists.txt b/CMakeLists.txt
@@ -4,7 +4,7 @@ include(cmake/prelude.cmake)
project(
stamd
VERSION 0.2.2
VERSION 0.2.3
DESCRIPTION "Static Markdown Page Generator"
HOMEPAGE_URL "https://git.dimitrijedobrota.com/stamd.git"
LANGUAGES CXX
@@ -15,17 +15,10 @@ include(cmake/variables.cmake)
# ---- Declare dependencies ----
find_package(md4c CONFIG REQUIRED)
find_package(poafloc 1 CONFIG REQUIRED)
find_package(hemplate 0.1 CONFIG REQUIRED)
include(FetchContent)
FetchContent_Declare(
maddy
URL https://github.com/progsource/maddy/releases/download/1.3.0/maddy-src.zip
)
FetchContent_MakeAvailable(maddy)
# ---- Declare library ----
@@ -54,7 +47,7 @@ set_property(TARGET stamd_exe PROPERTY OUTPUT_NAME stamd)
target_compile_features(stamd_exe PRIVATE cxx_std_20)
target_link_libraries(stamd_exe PRIVATE poafloc maddy stamd_lib)
target_link_libraries(stamd_exe PRIVATE poafloc md4c::md4c-html stamd_lib)
# ---- Install rules ----
diff --git a/source/article.cpp b/source/article.cpp
@@ -69,7 +69,7 @@ void article::print_categories(std::ostream& ost,
ost << html::nav();
}
void article::write(const std::string& data, std::ostream& ost)
void article::write_header(std::ostream& ost) const
{
using namespace hemplate; // NOLINT
@@ -128,8 +128,11 @@ void article::write(const std::string& data, std::ostream& ost)
.set("class", "switch_label");
if (!m_categories.empty()) print_categories(ost, m_categories);
}
ost << data;
void article::write_footer(std::ostream& ost) const
{
using namespace hemplate; // NOLINT
ost << html::main();
@@ -142,7 +145,9 @@ void article::write(const std::string& data, std::ostream& ost)
}
ost << html::div();
ost << html::script(" ").set("source", "/scripts/main.js");
ost << html::script(" ")
.set("type", "text/javascript")
.set("source", "/scripts/main.js");
ost << html::body();
ost << html::html();
}
diff --git a/source/article.hpp b/source/article.hpp
@@ -18,7 +18,9 @@ public:
{
}
void write(const std::string& data, std::ostream& ost);
void write_header(std::ostream& ost) const;
void write_footer(std::ostream& ost) const;
void insert(const std::string& category) { m_categories.emplace(category); }
void insert(const std::string& key, const std::string& value)
{
diff --git a/source/index.cpp b/source/index.cpp
@@ -1,4 +1,5 @@
#include <algorithm>
#include <chrono>
#include <format>
#include <fstream>
#include <numeric>
@@ -11,33 +12,32 @@
namespace stamd {
void create_index(const std::string& name,
void create_index(std::ostream& ost,
const std::string& name,
const article_list& articles,
const categories_t& categories)
{
using namespace hemplate; // NOLINT
std::ofstream ost(name + ".html");
std::stringstream strs;
const article index(name, categories);
strs << html::h1(name);
strs << html::ul().set("class", "index");
index.write_header(ost);
ost << html::h1(name);
ost << html::ul().set("class", "index");
for (const auto& article : articles)
{
if (article->is_hidden()) continue;
const auto& filename = article->get_filename();
const auto& title = article->get_title();
const auto& title = article->get_title();
const auto& date = article->get_date();
strs << html::li()
.add(html::div(std::format("{} - ", date)))
.add(html::div().add(html::a(title).set("href", filename)));
ost << html::li()
.add(html::span(std::format("{} - ", date)))
.add(html::a(title).set("href", filename));
};
strs << html::ul();
article index(name, categories);
index.write(strs.str(), ost);
ost << html::ul();
index.write_footer(ost);
}
void create_atom(std::ostream& ost,
@@ -48,9 +48,11 @@ void create_atom(std::ostream& ost,
static const char* base = "https://dimitrijedobrota.com/blog";
static const char* loc = "https://dimitrijedobrota.com/blog/atom.feed";
static const char* updated = "2003-12-13T18:30:02Z";
static const char* summary = "Click on the article link to read...";
auto const time =
std::chrono::current_zone()->to_local(std::chrono::system_clock::now());
const elementList content = std::accumulate(
begin(articles),
end(articles),
@@ -58,11 +60,13 @@ void create_atom(std::ostream& ost,
[](elementList&& list, const auto& article)
{
const auto filename = article->get_filename();
const auto date = article->get_date();
list.add(atom::entry()
.add(atom::title(filename))
.add(atom::link().set(
.add(atom::link(" ").set(
"href", std::format("{}/{}", base, filename)))
.add(atom::updated(updated))
.add(atom::updated(date))
.add(atom::summary(summary)));
return std::move(list);
});
@@ -70,14 +74,13 @@ void create_atom(std::ostream& ost,
ost << xml();
ost << atom::feed();
ost << atom::title(name);
ost << atom::link().set("href", base);
ost << atom::link({{"rel", "self"}, {"href", loc}});
ost << atom::link(" ").set("href", base);
ost << atom::link(" ", {{"rel", "self"}, {"href", loc}});
ost << atom::id(base);
ost << atom::updated(updated);
ost << atom::updated(std::format("{:%Y-%m-%d %X}", time));
ost << atom::author().add(atom::name(name));
ost << atom::feed();
ost << content;
ost << atom::feed(content);
ost << atom::feed();
}
void create_rss(std::ostream& ost,
@@ -90,8 +93,7 @@ void create_rss(std::ostream& ost,
static const char* email = "mail@dimitrijedobrota.com";
static const char* base = "https://dimitrijedobrota.com/blog";
static const char* description = "Contents of Dimitrije Dobrota's webpage";
static const char* loc = "https://dimitrijedobrota.com/blog/index.rss";
static const char* updated = "2003-12-13T18:30:02Z";
static const char* loc = "https://dimitrijedobrota.com/blog/index.rss";
const elementList content = std::accumulate(
begin(articles),
@@ -100,11 +102,13 @@ void create_rss(std::ostream& ost,
[](elementList&& list, const auto& article)
{
const auto filename = article->get_filename();
const auto date = article->get_date();
list.add(rss::item()
.add(rss::title(filename))
.add(rss::link(std::format("{}/{}", base, filename)))
.add(rss::guid(std::format("{}/{}", base, filename)))
.add(rss::pubDate(updated))
.add(rss::pubDate(date))
.add(rss::author(std::format("{} ({})", email, author))));
return std::move(list);
});
diff --git a/source/index.hpp b/source/index.hpp
@@ -22,7 +22,8 @@ void create_rss(std::ostream& ost,
const std::string& name,
const article_list& articles);
void create_index(const std::string& name,
void create_index(std::ostream& ost,
const std::string& name,
const article_list& articles,
const categories_t& categories);
diff --git a/source/main.cpp b/source/main.cpp
@@ -3,11 +3,11 @@
#include <iostream>
#include <sstream>
#include <md4c-html.h>
#include <poafloc/poafloc.hpp>
#include "article.hpp"
#include "index.hpp"
#include "maddy/parser.h"
#include "utility.hpp"
void preprocess(article& article, std::istream& ist)
@@ -43,7 +43,7 @@ void preprocess(article& article, std::istream& ist)
struct arguments_t
{
std::string output_dir = ".";
std::filesystem::path output_dir = ".";
std::vector<std::filesystem::path> files;
bool index = false;
@@ -89,6 +89,12 @@ static const poafloc::arg_t arg {
};
// NOLINTEND
void process_output(const MD_CHAR* str, MD_SIZE size, void* data)
{
std::ofstream& ofs = *static_cast<std::ofstream*>(data);
ofs << std::string(str, size);
}
int main(int argc, char* argv[])
{
using namespace stamd; // NOLINT
@@ -106,7 +112,6 @@ int main(int argc, char* argv[])
category_map_t category_map;
categories_t all_categories;
article_list all_articles;
maddy::Parser parser;
for (const auto& path : args.files)
{
@@ -119,8 +124,22 @@ int main(int argc, char* argv[])
preprocess(*article, ifs);
// filename can change in preprocessing phase
std::ofstream ofs(article->get_filename());
article->write(parser.Parse(ifs), ofs);
std::filesystem::path out = args.output_dir / article->get_filename();
std::ofstream ofs(out);
std::stringstream sst;
std::cerr << out.string() << std::endl;
sst << ifs.rdbuf();
article->write_header(ofs);
md_html(sst.str().c_str(),
static_cast<MD_SIZE>(sst.str().size()),
process_output,
&ofs,
MD_DIALECT_GITHUB,
0);
article->write_footer(ofs);
if (!article->is_hidden())
{
@@ -137,10 +156,11 @@ int main(int argc, char* argv[])
[](const auto& lft, const auto& rht)
{ return lft->get_date() > rht->get_date(); });
std::ofstream atom("atom.xml");
std::ofstream rss("rss.xml");
std::ofstream sitemap("sitemap.xml");
std::ofstream robots("robots.txt");
std::ofstream atom(args.output_dir / "atom.xml");
std::ofstream rss(args.output_dir / "rss.xml");
std::ofstream sitemap(args.output_dir / "sitemap.xml");
std::ofstream robots(args.output_dir / "robots.txt");
std::ofstream index(args.output_dir / "index.html");
create_sitemap(sitemap, all_articles);
create_robots(robots);
@@ -148,11 +168,12 @@ int main(int argc, char* argv[])
create_rss(rss, "index", all_articles);
create_atom(atom, "index", all_articles);
create_index("index", all_articles, all_categories);
create_index(index, "index", all_articles, all_categories);
for (const auto& [category, articles] : category_map)
{
auto ctgry = category;
create_index(normalize(ctgry), articles, {});
std::ofstream ost(args.output_dir / (normalize(ctgry) + ".html"));
create_index(ost, category, articles, {});
}
return 0;