stuff-from-scratch/apps/website-generator/WebsiteGenerator.cpp

160 lines
3.9 KiB
C++
Raw Normal View History

2022-10-09 16:39:46 +00:00
#include "WebsiteGenerator.h"
2022-10-11 19:20:12 +00:00
#include "TomlReader.h"
#include "Directory.h"
#include "ContentFile.h"
#include "ContentPage.h"
#include "TemplateFile.h"
#include "TemplatingEngine.h"
2022-12-05 17:50:49 +00:00
#include "TemplateSubstitutionContext.h"
#include "SiteGeneratorConfig.h"
#include "PathUtils.h"
2022-12-05 17:50:49 +00:00
#include "MarkdownConverter.h"
#include "HtmlElement.h"
#include "HtmlWriter.h"
#include "FileLogger.h"
#include <iostream>
WebsiteGenerator::WebsiteGenerator()
: mConfig(std::make_unique<SiteGeneratorConfig>()),
mTemplateEngine()
{
}
WebsiteGenerator::~WebsiteGenerator()
{
}
2022-10-11 19:20:12 +00:00
2022-10-09 16:39:46 +00:00
void WebsiteGenerator::findProject(const std::string& searchPath)
{
const auto config_path = std::filesystem::path(searchPath) / "config.toml";
if (std::filesystem::exists(config_path))
{
mProjectPath = searchPath;
MLOG_INFO("Found project config in: " << mProjectPath);
2022-10-09 16:39:46 +00:00
}
}
void WebsiteGenerator::findContentFiles()
{
const bool is_recursive{true};
const auto pages_files = Directory::getFilesWithExtension(getPagesPath(), ".md", is_recursive);
for (const auto& path : pages_files)
{
mPages.push_back(std::make_unique<ContentPage>(path));
}
const auto article_files = Directory::getFilesWithExtension(getArticlesPath(), ".md", is_recursive);
for (const auto& path : article_files)
{
mArticles.push_back(std::make_unique<ContentArticle>(path));
}
MLOG_INFO("Found: " << mArticles.size() << " articles");
}
Path WebsiteGenerator::getContentPath() const
{
return mProjectPath / "content";
}
Path WebsiteGenerator::getPagesPath() const
{
return getContentPath() / "pages";
}
Path WebsiteGenerator::getArticlesPath() const
{
return getContentPath() / "articles";
}
2022-10-09 16:39:46 +00:00
Path WebsiteGenerator::getConfigPath() const
{
2022-10-11 19:20:12 +00:00
return mProjectPath / "config.toml";
2022-10-09 16:39:46 +00:00
}
void WebsiteGenerator::readConfig()
{
2022-10-11 19:20:12 +00:00
auto reader = TomlReader();
reader.read(getConfigPath());
2022-10-09 16:39:46 +00:00
2022-10-11 19:20:12 +00:00
if (auto theme_table = reader.getContent()->getTable("themes"))
2022-10-09 16:39:46 +00:00
{
2022-10-11 19:20:12 +00:00
auto items = theme_table->getKeyValuePairs();
auto location = items["location"];
auto active_theme = items["active_theme"];
2022-10-09 16:39:46 +00:00
mConfig->setThemePath(location);
mConfig->setActiveTheme(active_theme);
2022-10-09 16:39:46 +00:00
}
}
void WebsiteGenerator::parseContentFiles()
{
findContentFiles();
for (auto& page : mPages)
{
page->load();
}
for (auto& article : mArticles)
{
article->load();
2022-10-09 16:39:46 +00:00
}
}
void WebsiteGenerator::parseTemplateFiles()
{
const auto template_path = mProjectPath / mConfig->getThemePath() / mConfig->getActiveTheme();
mTemplateEngine = std::make_unique<TemplatingEngine>(template_path);
2022-10-09 16:39:46 +00:00
}
void WebsiteGenerator::doSubstitutions()
{
2022-12-05 17:50:49 +00:00
MarkdownConverter converter;
for (auto& article : mArticles)
{
2022-12-05 17:50:49 +00:00
article->doLinkTagSubstitution(getArticlesPath());
auto containing_div = std::make_unique<HtmlDivElement>();
converter.convert(article->getContentBody(), containing_div.get());
HtmlWriter writer;
auto md_html_content = writer.toString(containing_div.get());
2022-10-09 16:39:46 +00:00
2022-12-05 17:50:49 +00:00
TemplateSubstitutionContext sub_context;
sub_context.addSubstitution("content", md_html_content);
auto content = mTemplateEngine->renderTemplate("article", &sub_context);
article->setProcessedOutput(content);
}
2022-10-09 16:39:46 +00:00
}
2022-12-05 17:50:49 +00:00
Path WebsiteGenerator::getOutputPath() const
{
return mProjectPath / "output";
}
2022-10-09 16:39:46 +00:00
void WebsiteGenerator::write()
{
// Setup output dir
const auto output_dir = mProjectPath / "output";
2022-10-09 16:39:46 +00:00
std::filesystem::create_directory(output_dir);
// Write each page
for (auto& article : mArticles)
2022-10-09 16:39:46 +00:00
{
auto article_path = article->getFilename();
auto relative_path = PathUtils::getRelativePath(article_path, getArticlesPath());
auto updated_filename = PathUtils::getPathDelimited(relative_path);
auto final_path = output_dir / Path(updated_filename).replace_extension(".html");
2022-12-05 17:50:49 +00:00
article->write(final_path);
2022-10-09 16:39:46 +00:00
}
}