Generate blog catalog

WebsiteBuilder now generates a blog catalog containing each article from
every blog.  Articles are sorted by published date and are grouped based
on their month and year.
This commit is contained in:
luca0N! 2022-04-26 23:54:12 -03:00
parent 4753920f3d
commit 304ed3013f
Signed by: luca0N
GPG Key ID: 2E7B4655CF16D7D6
3 changed files with 53 additions and 5 deletions

View File

@ -131,7 +131,7 @@ namespace Article {
fclose(a); fclose(a);
} }
bool Comparator::comp(Metadata *a, Metadata *b) { bool Comparator::comp(Metadata *a, Metadata *b) {
return a->publish_ts < b->publish_ts; return a->publish_ts > b->publish_ts;
} }
bool Comparator::equiv(Metadata *a, Metadata *b) { bool Comparator::equiv(Metadata *a, Metadata *b) {
return a->publish_ts == b->publish_ts; return a->publish_ts == b->publish_ts;

View File

@ -27,6 +27,7 @@ namespace Article {
struct Metadata { struct Metadata {
char title[128]; char title[128];
char authors[128]; // Author (or authors) for this article char authors[128]; // Author (or authors) for this article
char path[256]; // Path to this article
// Epoch timestamps // Epoch timestamps
long original_ts; // Original article timestamp (for "Originally written on [...]") long original_ts; // Original article timestamp (for "Originally written on [...]")

View File

@ -153,7 +153,6 @@ void build_blog_structure(std::string const &path, std::string const &prefix, st
Article::get_metadata(a, articleMetadata); Article::get_metadata(a, articleMetadata);
std::cout << "Parsed metadata for article \"" << articleMetadata->title << "\"\n\tPublished on " std::cout << "Parsed metadata for article \"" << articleMetadata->title << "\"\n\tPublished on "
<< ctime(&(articleMetadata->publish_ts)) << "\n"; << ctime(&(articleMetadata->publish_ts)) << "\n";
am.push_back(articleMetadata);
// TODO: This code could be optimized by removing directory // TODO: This code could be optimized by removing directory
// checks for every single article. Instead, add // checks for every single article. Instead, add
@ -162,18 +161,25 @@ void build_blog_structure(std::string const &path, std::string const &prefix, st
// directories later as needed. // directories later as needed.
try { try {
// Create directory for the year of this article if it doesn't exist. // Create directory for the year of this article if it doesn't exist.
std::filesystem::path oad = obp; // Output Article Directory std::filesystem::path oad = obp, // Output Article Directory
rap; // Relative Article Path
oad /= year; oad /= year;
rap /= year;
if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad); if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad);
// Do the same for the article month. // Do the same for the article month.
oad /= month; oad /= month;
rap /= month;
if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad); if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad);
// Now create the article file. // Now create the article file.
oad /= getFilename(a, false); std::string new_article_filename = getFilename(a, false);
oad += ".html"; new_article_filename += ".html";
oad /= new_article_filename;
rap /= new_article_filename;
compile_markdown(path, a, oad); compile_markdown(path, a, oad);
strncpy(articleMetadata->path, rap.c_str(), sizeof(articleMetadata->path));
am.push_back(articleMetadata);
} catch (std::filesystem::filesystem_error const &e) { } catch (std::filesystem::filesystem_error const &e) {
std::cerr << "error: failed to create directory for an article from blog \"" std::cerr << "error: failed to create directory for an article from blog \""
<< blog->name << "\": " << e.what() << std::endl; << blog->name << "\": " << e.what() << std::endl;
@ -182,6 +188,47 @@ void build_blog_structure(std::string const &path, std::string const &prefix, st
} }
// Sort am list. // Sort am list.
am.sort(Article::Comparator::comp); am.sort(Article::Comparator::comp);
// Generate blog catalog.
std::string blog_html_catalog = "<ul>",
last_date = "";
std::string hr_month[] = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
for (Article::Metadata *m : am) {
struct tm *article_time = gmtime(&(m->publish_ts));
std::string hr_date = hr_month[article_time->tm_mon];
hr_date += " ";
hr_date += std::to_string(article_time->tm_year + 1900);
// Check if this article belongs to the same "month + year" group as
// the last article. If it doesn't, add a new group to the catalog.
if (hr_date != last_date) {
last_date = hr_date;
blog_html_catalog += "<span><b>";
blog_html_catalog += hr_date;
blog_html_catalog += "</b></span>";
}
blog_html_catalog += "<li><a href=\"./";
blog_html_catalog += m->path;
blog_html_catalog += "\">";
blog_html_catalog += m->title;
blog_html_catalog += "</a></li>";
// Free memory as it's no longer needed.
free(m);
}
blog_html_catalog += "</ul>";
} }
/** /**