Minor code refactoring
Moved certain functions to proper locations and added new source files for minor refactoring.
This commit is contained in:
parent
647ad56349
commit
d97ef91db8
8 changed files with 309 additions and 198 deletions
141
src/BlogBuilder.cxx
Normal file
141
src/BlogBuilder.cxx
Normal file
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright (C) 2022 luca0N!
|
||||
*
|
||||
* This file is part of Static Website Generator (swg).
|
||||
*
|
||||
* Static Website Generator (swg) is free software: you can redistribute it
|
||||
* and/or modify it under the terms of the version 3 of the GNU Lesser General
|
||||
* Public License as published by the Free Software Foundation.
|
||||
*
|
||||
* Static Website Generator (swg) is distributed in the hope that it will be
|
||||
* useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
* General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Static Website Generator (swg). If not, see
|
||||
* <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* Contact luca0N! by e-mail: <luca0n [at] luca0n [dot] com>.
|
||||
*/
|
||||
|
||||
#include "BlogBuilder.hxx"
|
||||
|
||||
#include <regex>
|
||||
#include <iostream>
|
||||
|
||||
#include "Article.hxx"
|
||||
#include "WebsiteBuilder.hxx"
|
||||
|
||||
std::string blog_relative_path(std::string const &pathPrefix, std::string const &path) {
|
||||
return path.substr(pathPrefix.length() - 1);
|
||||
}
|
||||
|
||||
bool is_valid_article(std::string const &pathPrefix, std::string const &path) {
|
||||
return std::regex_search(blog_relative_path(pathPrefix, path), std::regex("^/\\d{4}/\\d{2}/.*\\.md"));
|
||||
}
|
||||
void build_blog_structure(std::string const &path, std::string const &prefix, std::list<std::string> const &articles, Blog *blog) {
|
||||
std::filesystem::path obp = get_output_path(path); // Output Blog Path
|
||||
obp /= "blog";
|
||||
obp /= blog->dir;
|
||||
try {
|
||||
// Create blog directory
|
||||
if (!std::filesystem::exists(obp)) std::filesystem::create_directories(obp);
|
||||
} catch (std::filesystem::filesystem_error const &e) {
|
||||
std::cerr << "error: failed to create directory for blog \"" << blog->name << "\": " << e.what() << std::endl;
|
||||
exit(RETURN_FAILED_UNKNOWN_ERROR);
|
||||
}
|
||||
|
||||
std::list<Article::Metadata*> am;
|
||||
//std::map<std::string, std::list<std::string>> sorted_articles;
|
||||
|
||||
for (std::string const &a : articles) {
|
||||
std::string articlePath = blog_relative_path(prefix, a);
|
||||
std::regex yearMonth("(\\d+)");
|
||||
auto match = std::sregex_iterator(articlePath.begin(), articlePath.end(), yearMonth);
|
||||
|
||||
std::string year = match->str(),
|
||||
month = (++match)->str();
|
||||
|
||||
// Go ahead and parse article metadata.
|
||||
Article::Metadata *articleMetadata = (Article::Metadata*) malloc(sizeof(Article::Metadata));
|
||||
Article::get_metadata(a, articleMetadata);
|
||||
std::cout << "Parsed metadata for article \"" << articleMetadata->title << "\"\n\tPublished on "
|
||||
<< ctime(&(articleMetadata->publish_ts)) << "\n";
|
||||
|
||||
// TODO: This code could be optimized by removing directory
|
||||
// checks for every single article. Instead, add
|
||||
// directory-checks for years and months to a queue (skipping
|
||||
// existing ones) and then checking and creating the
|
||||
// directories later as needed.
|
||||
try {
|
||||
// Create directory for the year of this article if it doesn't exist.
|
||||
std::filesystem::path oad = obp, // Output Article Directory
|
||||
rap; // Relative Article Path
|
||||
oad /= year;
|
||||
rap /= year;
|
||||
if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad);
|
||||
|
||||
// Do the same for the article month.
|
||||
oad /= month;
|
||||
rap /= month;
|
||||
if (!std::filesystem::exists(oad)) std::filesystem::create_directory(oad);
|
||||
|
||||
// Now create the article file.
|
||||
std::string new_article_filename = getFilename(a, false);
|
||||
new_article_filename += ".html";
|
||||
oad /= new_article_filename;
|
||||
rap /= new_article_filename;
|
||||
compile_markdown(path, a, oad, articleMetadata);
|
||||
strncpy(articleMetadata->path, rap.c_str(), sizeof(articleMetadata->path));
|
||||
am.push_back(articleMetadata);
|
||||
} catch (std::filesystem::filesystem_error const &e) {
|
||||
std::cerr << "error: failed to create directory for an article from blog \""
|
||||
<< blog->name << "\": " << e.what() << std::endl;
|
||||
exit(RETURN_FAILED_UNKNOWN_ERROR);
|
||||
}
|
||||
}
|
||||
// Sort am list.
|
||||
am.sort(Article::Comparator::comp);
|
||||
// Generate blog catalog.
|
||||
std::string blog_html_catalog,
|
||||
last_date = "";
|
||||
blog_html_catalog += "<h2>";
|
||||
blog_html_catalog += blog->name;
|
||||
blog_html_catalog += " - Catalog</h2>\n<ul>";
|
||||
|
||||
for (Article::Metadata *m : am) {
|
||||
struct tm *article_time = gmtime(&(m->publish_ts));
|
||||
std::string hr_date = get_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 += "\n\t<span><b>";
|
||||
blog_html_catalog += hr_date;
|
||||
blog_html_catalog += "</b></span>\n";
|
||||
}
|
||||
blog_html_catalog += "\t<li><a href=\"./";
|
||||
blog_html_catalog += m->path;
|
||||
blog_html_catalog += "\">";
|
||||
blog_html_catalog += m->title;
|
||||
blog_html_catalog += "</a></li>\n";
|
||||
// Free memory as it's no longer needed.
|
||||
free(m);
|
||||
}
|
||||
blog_html_catalog += "</ul>";
|
||||
// Put catalog HTML into template and save it to the blog directory.
|
||||
std::filesystem::path catalog_output_path = obp;
|
||||
catalog_output_path /= "index.html";
|
||||
|
||||
std::string html_template = get_template(path);
|
||||
std::regex content_placeholder("<!--\\[_SWG: \\$CONTENT\\]-->");
|
||||
std::string catalog_html_contents = std::regex_replace(html_template, content_placeholder, blog_html_catalog);
|
||||
|
||||
FILE *catalog_output_file = fopen(catalog_output_path.c_str(), "w");
|
||||
fputs(catalog_html_contents.c_str(), catalog_output_file);
|
||||
fclose(catalog_output_file);
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue