2022-10-09 16:39:46 +00:00
|
|
|
#include "WebsiteGenerator.h"
|
|
|
|
|
2022-10-11 19:20:12 +00:00
|
|
|
#include "TomlReader.h"
|
2022-12-05 13:16:10 +00:00
|
|
|
#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"
|
2022-12-05 13:16:10 +00:00
|
|
|
#include "SiteGeneratorConfig.h"
|
|
|
|
#include "PathUtils.h"
|
|
|
|
|
2022-12-05 17:50:49 +00:00
|
|
|
#include "MarkdownConverter.h"
|
|
|
|
#include "HtmlElement.h"
|
|
|
|
#include "HtmlWriter.h"
|
|
|
|
|
2022-12-05 13:16:10 +00:00
|
|
|
#include "FileLogger.h"
|
|
|
|
|
2022-12-07 10:21:28 +00:00
|
|
|
#include <iostream>
|
|
|
|
|
2022-12-05 13:16:10 +00:00
|
|
|
WebsiteGenerator::WebsiteGenerator()
|
|
|
|
: mConfig(std::make_unique<SiteGeneratorConfig>()),
|
|
|
|
mTemplateEngine()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
WebsiteGenerator::~WebsiteGenerator()
|
|
|
|
{
|
|
|
|
|
|
|
|
}
|
2022-10-11 19:20:12 +00:00
|
|
|
|
2023-12-21 09:18:44 +00:00
|
|
|
void WebsiteGenerator::findProject(const String& searchPath)
|
2022-10-09 16:39:46 +00:00
|
|
|
{
|
|
|
|
const auto config_path = std::filesystem::path(searchPath) / "config.toml";
|
|
|
|
if (std::filesystem::exists(config_path))
|
|
|
|
{
|
|
|
|
mProjectPath = searchPath;
|
2022-12-05 13:16:10 +00:00
|
|
|
MLOG_INFO("Found project config in: " << mProjectPath);
|
2022-10-09 16:39:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-12-05 13:16:10 +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
|
|
|
|
2022-12-05 13:16:10 +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)
|
|
|
|
{
|
2022-12-05 13:16:10 +00:00
|
|
|
page->load();
|
|
|
|
}
|
|
|
|
|
|
|
|
for (auto& article : mArticles)
|
|
|
|
{
|
|
|
|
article->load();
|
2022-10-09 16:39:46 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void WebsiteGenerator::parseTemplateFiles()
|
|
|
|
{
|
2022-12-05 13:16:10 +00:00
|
|
|
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;
|
|
|
|
|
2022-12-05 13:16:10 +00:00
|
|
|
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-12-05 13:16:10 +00:00
|
|
|
}
|
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
|
2022-12-05 13:16:10 +00:00
|
|
|
const auto output_dir = mProjectPath / "output";
|
2022-10-09 16:39:46 +00:00
|
|
|
std::filesystem::create_directory(output_dir);
|
|
|
|
|
|
|
|
// Write each page
|
2022-12-05 13:16:10 +00:00
|
|
|
for (auto& article : mArticles)
|
2022-10-09 16:39:46 +00:00
|
|
|
{
|
2022-12-05 13:16:10 +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
|
|
|
}
|
|
|
|
}
|
|
|
|
|