From f44c79dc1f5341bb0260994325c5d720ad6b80f9 Mon Sep 17 00:00:00 2001 From: James Grogan Date: Mon, 5 Dec 2022 13:16:10 +0000 Subject: [PATCH] Start adding markdown conversion to site generator. --- apps/website-generator/CMakeLists.txt | 11 +- apps/website-generator/ContentFile.cpp | 54 ++++ apps/website-generator/ContentFile.h | 74 ++--- apps/website-generator/ContentPage.cpp | 14 + apps/website-generator/ContentPage.h | 11 + .../MarkdownContentParser.cpp | 30 ++- .../website-generator/MarkdownContentParser.h | 19 +- .../website-generator/SiteGeneratorConfig.cpp | 21 ++ apps/website-generator/SiteGeneratorConfig.h | 22 ++ apps/website-generator/SiteTemplateFile.h | 18 ++ apps/website-generator/WebsiteGenerator.cpp | 115 +++++--- apps/website-generator/WebsiteGenerator.h | 68 ++--- apps/website-generator/main.cpp | 3 +- src/compiler/TemplatingEngine.cpp | 16 +- src/compiler/TemplatingEngine.h | 5 +- src/core/CMakeLists.txt | 29 +- src/core/file_utilities/Directory.cpp | 7 +- src/core/file_utilities/Directory.h | 2 +- src/core/file_utilities/File.cpp | 5 - src/core/file_utilities/File.h | 3 - src/core/file_utilities/PathUtils.cpp | 33 +++ src/core/file_utilities/PathUtils.h | 17 ++ src/web/CMakeLists.txt | 4 + src/web/markdown/MarkdownComponents.cpp | 122 +++++++++ src/web/markdown/MarkdownComponents.h | 124 +++++++++ src/web/markdown/MarkdownConverter.cpp | 2 + src/web/markdown/MarkdownDocument.cpp | 18 ++ src/web/markdown/MarkdownDocument.h | 254 +----------------- src/web/markdown/MarkdownElement.cpp | 11 + src/web/markdown/MarkdownElement.h | 40 +++ src/web/markdown/MarkdownParser.cpp | 1 + 31 files changed, 692 insertions(+), 461 deletions(-) create mode 100644 apps/website-generator/ContentPage.cpp create mode 100644 apps/website-generator/ContentPage.h create mode 100644 apps/website-generator/SiteGeneratorConfig.cpp create mode 100644 apps/website-generator/SiteGeneratorConfig.h create mode 100644 apps/website-generator/SiteTemplateFile.h create mode 100644 src/core/file_utilities/PathUtils.cpp create mode 100644 src/core/file_utilities/PathUtils.h create mode 100644 src/web/markdown/MarkdownComponents.cpp create mode 100644 src/web/markdown/MarkdownComponents.h create mode 100644 src/web/markdown/MarkdownElement.cpp create mode 100644 src/web/markdown/MarkdownElement.h diff --git a/apps/website-generator/CMakeLists.txt b/apps/website-generator/CMakeLists.txt index 3acb632..63e3775 100644 --- a/apps/website-generator/CMakeLists.txt +++ b/apps/website-generator/CMakeLists.txt @@ -2,19 +2,24 @@ list(APPEND website_generator_LIB_INCLUDES ContentFile.h ContentFile.cpp + ContentPage.h + ContentPage.cpp MarkdownContentParser.h MarkdownContentParser.cpp + SiteGeneratorConfig.h + SiteGeneratorConfig.cpp WebsiteGenerator.h - WebsiteGenerator.cpp) + WebsiteGenerator.cpp + ) add_executable(website_generator main.cpp ${website_generator_LIB_INCLUDES}) target_include_directories(website_generator PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}" + ${CMAKE_CURRENT_SOURCE_DIR} ) -target_link_libraries(website_generator PUBLIC core web) +target_link_libraries(website_generator PUBLIC core web compiler) set_property(TARGET website_generator PROPERTY FOLDER apps/website-generator) diff --git a/apps/website-generator/ContentFile.cpp b/apps/website-generator/ContentFile.cpp index e69de29..a7ca1f4 100644 --- a/apps/website-generator/ContentFile.cpp +++ b/apps/website-generator/ContentFile.cpp @@ -0,0 +1,54 @@ +#include "ContentFile.h" + +#include "PathUtils.h" +#include "MarkdownDocument.h" +#include "MarkdownElement.h" + +ContentFile::ContentFile(const Path& filename) + : mFilename(filename) +{ + +} + +ContentFile::~ContentFile() +{ + +} + +Path ContentFile::getFilename() const +{ + return mFilename; +} + +std::string ContentFile::getOutputLocation() const +{ + const auto metadata_item = getMetadataItem("save_as"); + return metadata_item.empty() ? PathUtils::getBaseFilename(mFilename) : metadata_item; +} + +void ContentFile::load() +{ + MarkdownContentParser parser; + auto result = parser.run(mFilename); + + mMetadata = result.first; + mContentBody = std::move(result.second); +} + +std::string ContentFile::getMetadataItem(const std::string& key) const +{ + const auto check = mMetadata.find(key); + if (check == mMetadata.end()) + { + return {}; + } + else + { + return check->second; + } +} + +void ContentFile::write(const Path& path) +{ + +} diff --git a/apps/website-generator/ContentFile.h b/apps/website-generator/ContentFile.h index c5f9a12..3382f2c 100644 --- a/apps/website-generator/ContentFile.h +++ b/apps/website-generator/ContentFile.h @@ -7,73 +7,37 @@ #include #include +class MarkdownDocument; + class ContentFile { public: using FileMetadata = std::unordered_map; using FileContentBody = std::vector; - ContentFile(const Path& filename) - : mFilename(filename) - { + ContentFile(const Path& filename); + virtual ~ContentFile(); + + Path getFilename() const; + + virtual void load(); + + std::string getMetadataItem(const std::string& key) const; + + virtual std::string getOutputLocation() const; + + MarkdownDocument* getContentBody() const + { + return mContentBody.get(); } - virtual ~ContentFile() = default; - - Path getFilename() const - { - return mFilename; - } - - virtual void load() - { - MarkdownContentParser parser; - parser.run(mFilename); - - mMetadata = parser.getFileMetadata(); - mContentBody = parser.getContentBody(); - } - - std::string getMetadataItem(const std::string& key) const - { - const auto check = mMetadata.find(key); - if (check == mMetadata.end()) - { - return {}; - } - else - { - return check->second; - } - } - + void write(const Path& path); protected: Path mFilename; FileMetadata mMetadata; - FileContentBody mContentBody; -}; - -class ContentPage : public ContentFile -{ -public: - - ContentPage(const Path& filename) - : ContentFile(filename) - { - - } - - void load() override - { - ContentFile::load(); - } - - std::string getOutputLocation() const - { - const auto metadata_item = getMetadataItem("save_as"); - return metadata_item.empty() ? File::getBaseFilename(mFilename) : metadata_item; - } + std::unique_ptr mContentBody; + std::string mProcessedOutput; }; class ContentArticle : public ContentFile diff --git a/apps/website-generator/ContentPage.cpp b/apps/website-generator/ContentPage.cpp new file mode 100644 index 0000000..ebb0214 --- /dev/null +++ b/apps/website-generator/ContentPage.cpp @@ -0,0 +1,14 @@ +#include "ContentPage.h" + +ContentPage::ContentPage(const Path& filename) + : ContentFile(filename) +{ + +} + +void ContentPage::load() +{ + ContentFile::load(); +} + + diff --git a/apps/website-generator/ContentPage.h b/apps/website-generator/ContentPage.h new file mode 100644 index 0000000..b911a57 --- /dev/null +++ b/apps/website-generator/ContentPage.h @@ -0,0 +1,11 @@ +#pragma once + +#include "ContentFile.h" + +class ContentPage : public ContentFile +{ +public: + ContentPage(const Path& filename); + + void load() override; +}; diff --git a/apps/website-generator/MarkdownContentParser.cpp b/apps/website-generator/MarkdownContentParser.cpp index c9b357d..09908cb 100644 --- a/apps/website-generator/MarkdownContentParser.cpp +++ b/apps/website-generator/MarkdownContentParser.cpp @@ -1,11 +1,20 @@ #include "MarkdownContentParser.h" -void MarkdownContentParser::run(const Path& path) +#include "MarkdownParser.h" +#include "MarkdownDocument.h" +#include "MarkdownElement.h" + +#include "File.h" + +std::pair> MarkdownContentParser::run(const Path& path) { FileMetadata metadata; + FileMetadata output_metadata; const auto lines = File(path).readLines(); bool metadata_finished = false; + + std::string content_body; for (const auto& line : lines) { if (!metadata_finished) @@ -14,28 +23,23 @@ void MarkdownContentParser::run(const Path& path) if (!metadata) { metadata_finished = true; - mContentBody.push_back(line); + content_body += line + '\n'; } else { - mMetadata[metadata->first] = metadata->second; + output_metadata[metadata->first] = metadata->second; } } else { - mContentBody.push_back(line); + content_body += line + '\n'; } } -} -MarkdownContentParser::FileContentBody MarkdownContentParser::getContentBody() const -{ - return mContentBody; -} + MarkdownParser md_parser; + auto content = md_parser.run(content_body); -MarkdownContentParser::FileMetadata MarkdownContentParser::getFileMetadata() const -{ - return mMetadata; + return {output_metadata, std::move(content)}; } std::optional MarkdownContentParser::checkForMetadataItem(const std::string& line) const @@ -69,4 +73,4 @@ std::optional MarkdownContentParser::ch { return std::nullopt; } -} \ No newline at end of file +} diff --git a/apps/website-generator/MarkdownContentParser.h b/apps/website-generator/MarkdownContentParser.h index 44f4f5c..5ab4f0c 100644 --- a/apps/website-generator/MarkdownContentParser.h +++ b/apps/website-generator/MarkdownContentParser.h @@ -1,27 +1,22 @@ #pragma once -#include "File.h" - #include #include #include +#include +#include + +using Path = std::filesystem::path; + +class MarkdownDocument; class MarkdownContentParser { public: using FileMetadataItem = std::pair; using FileMetadata = std::unordered_map; - using FileContentBody = std::vector; - - void run(const Path& path); - - FileContentBody getContentBody() const; - - FileMetadata getFileMetadata() const; + std::pair> run(const Path& path); private: std::optional checkForMetadataItem(const std::string& line) const; - - FileMetadata mMetadata; - FileContentBody mContentBody; }; diff --git a/apps/website-generator/SiteGeneratorConfig.cpp b/apps/website-generator/SiteGeneratorConfig.cpp new file mode 100644 index 0000000..dd3375a --- /dev/null +++ b/apps/website-generator/SiteGeneratorConfig.cpp @@ -0,0 +1,21 @@ +#include "SiteGeneratorConfig.h" + +Path SiteGeneratorConfig::getThemePath() const +{ + return mThemesPath; +} + +std::string SiteGeneratorConfig::getActiveTheme() const +{ + return mActiveTheme; +} + +void SiteGeneratorConfig::setThemePath(const Path& path) +{ + mThemesPath = path; +} + +void SiteGeneratorConfig::setActiveTheme(const std::string& theme) +{ + mActiveTheme = theme; +} diff --git a/apps/website-generator/SiteGeneratorConfig.h b/apps/website-generator/SiteGeneratorConfig.h new file mode 100644 index 0000000..0970113 --- /dev/null +++ b/apps/website-generator/SiteGeneratorConfig.h @@ -0,0 +1,22 @@ +#pragma once + +#include +#include + +using Path = std::filesystem::path; + +class SiteGeneratorConfig +{ +public: + Path getThemePath() const; + + std::string getActiveTheme() const; + + void setThemePath(const Path& path); + + void setActiveTheme(const std::string& theme); + +private: + Path mThemesPath; + std::string mActiveTheme; +}; diff --git a/apps/website-generator/SiteTemplateFile.h b/apps/website-generator/SiteTemplateFile.h new file mode 100644 index 0000000..cfe63d4 --- /dev/null +++ b/apps/website-generator/SiteTemplateFile.h @@ -0,0 +1,18 @@ +#pragma once + +#include + +using Path = std::filesystem::path; + +class SiteTemplateFile +{ +public: + SiteTemplateFile(const Path& path) + : mPath(path) + { + + } + +private: + Path mPath; +}; diff --git a/apps/website-generator/WebsiteGenerator.cpp b/apps/website-generator/WebsiteGenerator.cpp index 8809d05..6db378f 100644 --- a/apps/website-generator/WebsiteGenerator.cpp +++ b/apps/website-generator/WebsiteGenerator.cpp @@ -1,6 +1,27 @@ #include "WebsiteGenerator.h" #include "TomlReader.h" +#include "Directory.h" +#include "ContentFile.h" +#include "ContentPage.h" +#include "TemplateFile.h" +#include "TemplatingEngine.h" +#include "SiteGeneratorConfig.h" +#include "PathUtils.h" + +#include "FileLogger.h" + +WebsiteGenerator::WebsiteGenerator() + : mConfig(std::make_unique()), + mTemplateEngine() +{ + +} + +WebsiteGenerator::~WebsiteGenerator() +{ + +} void WebsiteGenerator::findProject(const std::string& searchPath) { @@ -8,10 +29,42 @@ void WebsiteGenerator::findProject(const std::string& searchPath) if (std::filesystem::exists(config_path)) { mProjectPath = searchPath; - std::cout << "Found config.toml in " << searchPath << std::endl; + MLOG_INFO("Found project config in: " << mProjectPath); } } +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(path)); + } + + const auto article_files = Directory::getFilesWithExtension(getArticlesPath(), ".md", is_recursive); + for (const auto& path : article_files) + { + mArticles.push_back(std::make_unique(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"; +} + Path WebsiteGenerator::getConfigPath() const { return mProjectPath / "config.toml"; @@ -28,72 +81,54 @@ void WebsiteGenerator::readConfig() auto location = items["location"]; auto active_theme = items["active_theme"]; - mConfig.setThemePath(location); - mConfig.setActiveTheme(active_theme); + mConfig->setThemePath(location); + mConfig->setActiveTheme(active_theme); } } void WebsiteGenerator::parseContentFiles() { findContentFiles(); - for (auto& page : mPages) { - page.load(); + page->load(); + } + + for (auto& article : mArticles) + { + article->load(); } } void WebsiteGenerator::parseTemplateFiles() { - const auto template_path = mProjectPath / mConfig.getThemePath() / mConfig.getActiveTheme(); - - const auto template_files = Directory::getFilesWithExtension(template_path, ".html"); - for (const auto& path : template_files) - { - mTemplateFiles[path.stem().string()] = std::make_unique(path); - } + const auto template_path = mProjectPath / mConfig->getThemePath() / mConfig->getActiveTheme(); + mTemplateEngine = std::make_unique(template_path); + mTemplateEngine->loadTemplateFiles(); } void WebsiteGenerator::doSubstitutions() { + auto article_template = mTemplateEngine->processTemplate("article"); + for (auto& article : mArticles) + { + } } void WebsiteGenerator::write() { // Setup output dir - const auto output_dir = mProjectPath / "output_custom"; + const auto output_dir = mProjectPath / "output"; std::filesystem::create_directory(output_dir); // Write each page -} - -void WebsiteGenerator::findContentFiles() -{ - const auto pages_files = Directory::getFilesWithExtension(getPagesPath(), ".md"); - for (const auto& path : pages_files) + for (auto& article : mArticles) { - mPages.push_back(ContentPage(path)); - } - - const auto article_files = Directory::getFilesWithExtension(getArticlesPath(), ".md"); - for (const auto& path : article_files) - { - mArticles.push_back(ContentArticle(path)); + 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"); } } -Path WebsiteGenerator::getContentPath() const -{ - return mProjectPath / "content"; -} - -Path WebsiteGenerator::getPagesPath() const -{ - return getContentPath() / "pages"; -} - -Path WebsiteGenerator::getArticlesPath() const -{ - return getContentPath() / "articles"; -} diff --git a/apps/website-generator/WebsiteGenerator.h b/apps/website-generator/WebsiteGenerator.h index fb9a53c..343ad81 100644 --- a/apps/website-generator/WebsiteGenerator.h +++ b/apps/website-generator/WebsiteGenerator.h @@ -1,72 +1,38 @@ #pragma once -#include "Directory.h" -#include "ContentFile.h" - #include #include #include +#include #include -class GeneratorConfig -{ -public: - void setThemePath(const Path& path) - { - mThemesPath = path; - } +using Path = std::filesystem::path; - void setActiveTheme(const std::string& theme) - { - mActiveTheme = theme; - } - - Path getThemePath() const - { - return mThemesPath; - } - - std::string getActiveTheme() const - { - return mActiveTheme; - } - -private: - Path mThemesPath; - std::string mActiveTheme; -}; - -class TemplateFile -{ -public: - TemplateFile(const Path& path) - : mPath(path) - { - - } - -private: - Path mPath; -}; +class SiteGeneratorConfig; +class ContentPage; +class ContentArticle; +class TemplatingEngine; class WebsiteGenerator { public: + WebsiteGenerator(); + + ~WebsiteGenerator(); + + void doSubstitutions(); void findProject(const std::string& searchPath); - void readConfig(); - void parseContentFiles(); void parseTemplateFiles(); - void doSubstitutions(); + void readConfig(); void write(); private: - void findContentFiles(); Path getContentPath() const; @@ -78,8 +44,10 @@ private: Path getConfigPath() const; std::filesystem::path mProjectPath; - GeneratorConfig mConfig; - std::vector mPages; - std::vector mArticles; - std::unordered_map > mTemplateFiles; + + std::unique_ptr mConfig; + std::unique_ptr mTemplateEngine; + + std::vector > mPages; + std::vector > mArticles; }; diff --git a/apps/website-generator/main.cpp b/apps/website-generator/main.cpp index d1e68e7..65a8dde 100644 --- a/apps/website-generator/main.cpp +++ b/apps/website-generator/main.cpp @@ -2,7 +2,6 @@ #include "WebsiteGenerator.h" - int main(int argc, char *argv[]) { auto args = CommandLineArgs::Create(); @@ -21,10 +20,10 @@ int main(int argc, char *argv[]) generator.parseTemplateFiles(); // Substitute template files + generator.doSubstitutions(); // Write output generator.write(); - return 0; } diff --git a/src/compiler/TemplatingEngine.cpp b/src/compiler/TemplatingEngine.cpp index 3d00581..9cb7999 100644 --- a/src/compiler/TemplatingEngine.cpp +++ b/src/compiler/TemplatingEngine.cpp @@ -1,6 +1,7 @@ #include "TemplatingEngine.h" #include "Directory.h" +#include "FileLogger.h" #include @@ -13,10 +14,11 @@ TemplatingEngine::TemplatingEngine(const Path& workingDirectory) void TemplatingEngine::loadTemplateFiles() { const auto files = Directory::getFilesWithExtension(mWorkingDirectory, mTemplateExtension); - for (const auto& file : files) + for (const auto& path : files) { - mTemplateFiles.push_back(std::make_unique(file)); + mTemplateFiles[path.stem().string()] = std::make_unique(path); } + MLOG_INFO("Found: " << mTemplateFiles.size() << " templates in " << mWorkingDirectory); } std::string TemplatingEngine::processTemplate(const std::string& name) @@ -35,15 +37,7 @@ TemplateFile* TemplatingEngine::getTemplateFile(const Path& path) TemplateFile* TemplatingEngine::getTemplateFile(const std::string& name) { - //std::cout << "Looking for template file with name: " << name << std::endl; - for (const auto& file : mTemplateFiles) - { - if (file->getName() == name) - { - return file.get(); - } - } - return nullptr; + return mTemplateFiles[name].get(); } std::string TemplatingEngine::processTemplate(TemplateFile* file, TemplateNode* parent) diff --git a/src/compiler/TemplatingEngine.h b/src/compiler/TemplatingEngine.h index d9a33aa..9c92deb 100644 --- a/src/compiler/TemplatingEngine.h +++ b/src/compiler/TemplatingEngine.h @@ -5,6 +5,8 @@ #include #include +#include +#include class TemplatingEngine { @@ -14,7 +16,6 @@ public: void loadTemplateFiles(); std::string processTemplate(const std::string& name); - private: TemplateFile* getTemplateFile(const std::string& name); TemplateFile* getTemplateFile(const Path& path); @@ -22,7 +23,7 @@ private: std::string processTemplate(TemplateFile* file, TemplateNode* parent = nullptr); - std::vector > mTemplateFiles; + std::unordered_map > mTemplateFiles; Path mWorkingDirectory; std::string mTemplateExtension{ ".html" }; }; diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 2227000..2d78edb 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1,3 +1,5 @@ +set(MODULE_NAME core) + list(APPEND core_HEADERS AbstractApp.h Dictionary.h @@ -8,6 +10,7 @@ list(APPEND core_HEADERS file_utilities/Directory.h file_utilities/File.h file_utilities/FileFormats.h + file_utilities/PathUtils.h StringUtils.h http/HttpResponse.h serializers/TomlReader.h @@ -25,6 +28,7 @@ list(APPEND core_LIB_INCLUDES file_utilities/Directory.cpp file_utilities/File.cpp file_utilities/FileFormats.cpp + file_utilities/PathUtils.cpp memory/SharedMemory.cpp RandomUtils.cpp StringUtils.cpp @@ -38,18 +42,17 @@ list(APPEND core_LIB_INCLUDES http/HttpRequest.cpp serializers/TomlReader.cpp) -# add the executable -add_library(core SHARED ${core_LIB_INCLUDES} ${core_HEADERS}) +add_library(${MODULE_NAME} SHARED ${core_LIB_INCLUDES} ${core_HEADERS}) -target_include_directories(core PUBLIC - "${CMAKE_CURRENT_SOURCE_DIR}" - "${CMAKE_CURRENT_SOURCE_DIR}/file_utilities" - "${CMAKE_CURRENT_SOURCE_DIR}/loggers" - "${CMAKE_CURRENT_SOURCE_DIR}/memory" - "${CMAKE_CURRENT_SOURCE_DIR}/streams" - "${CMAKE_CURRENT_SOURCE_DIR}/http" - "${CMAKE_CURRENT_SOURCE_DIR}/data_structures" - "${CMAKE_CURRENT_SOURCE_DIR}/serializers" +target_include_directories(${MODULE_NAME} PUBLIC + ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_SOURCE_DIR}/file_utilities + ${CMAKE_CURRENT_SOURCE_DIR}/loggers + ${CMAKE_CURRENT_SOURCE_DIR}/memory + ${CMAKE_CURRENT_SOURCE_DIR}/streams + ${CMAKE_CURRENT_SOURCE_DIR}/http + ${CMAKE_CURRENT_SOURCE_DIR}/data_structures + ${CMAKE_CURRENT_SOURCE_DIR}/serializers ) -set_target_properties( core PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) -set_property(TARGET core PROPERTY FOLDER src) \ No newline at end of file +set_target_properties( ${MODULE_NAME} PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON ) +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER src) \ No newline at end of file diff --git a/src/core/file_utilities/Directory.cpp b/src/core/file_utilities/Directory.cpp index 1bffcd4..3492d91 100644 --- a/src/core/file_utilities/Directory.cpp +++ b/src/core/file_utilities/Directory.cpp @@ -1,6 +1,6 @@ #include "Directory.h" -std::vector Directory::getFilesWithExtension(const Path& path, const std::string& extension) +std::vector Directory::getFilesWithExtension(const Path& path, const std::string& extension, bool recursive) { std::vector paths; if (std::filesystem::is_directory(path)) @@ -11,6 +11,11 @@ std::vector Directory::getFilesWithExtension(const Path& path, const std:: { paths.push_back(entry.path()); } + else if(recursive && std::filesystem::is_directory(entry)) + { + const auto child_paths = getFilesWithExtension(entry, extension, recursive); + paths.insert(paths.end(), child_paths.begin(), child_paths.end()); + } } } return paths; diff --git a/src/core/file_utilities/Directory.h b/src/core/file_utilities/Directory.h index dcd47a1..e038078 100644 --- a/src/core/file_utilities/Directory.h +++ b/src/core/file_utilities/Directory.h @@ -9,5 +9,5 @@ class Directory { public: - static std::vector getFilesWithExtension(const Path& path, const std::string& extension); + static std::vector getFilesWithExtension(const Path& path, const std::string& extension, bool recursive=false); }; diff --git a/src/core/file_utilities/File.cpp b/src/core/file_utilities/File.cpp index 484e8c0..207dfeb 100644 --- a/src/core/file_utilities/File.cpp +++ b/src/core/file_utilities/File.cpp @@ -197,11 +197,6 @@ std::string File::read() return buffer.str(); } -std::string File::getBaseFilename(const Path& path) -{ - return path.stem().string(); -} - std::string File::readText() { if (!pathExists()) diff --git a/src/core/file_utilities/File.h b/src/core/file_utilities/File.h index b5acba0..b2cb3f0 100644 --- a/src/core/file_utilities/File.h +++ b/src/core/file_utilities/File.h @@ -20,7 +20,6 @@ public: }; public: - File(std::filesystem::path fullPath); ~File(); @@ -29,8 +28,6 @@ public: std::string dumpBinary(); - static std::string getBaseFilename(const Path& path); - std::string getExtension() const; std::ifstream* getInHandle() const; diff --git a/src/core/file_utilities/PathUtils.cpp b/src/core/file_utilities/PathUtils.cpp new file mode 100644 index 0000000..a56c0bb --- /dev/null +++ b/src/core/file_utilities/PathUtils.cpp @@ -0,0 +1,33 @@ +#include "PathUtils.h" + + +std::string PathUtils::getBaseFilename(const Path& path) +{ + return path.stem().string(); +} + +Path PathUtils::getRelativePath(const Path& input, const Path& relativeTo) +{ + return std::filesystem::relative(input, relativeTo); +} + +std::string PathUtils::getPathDelimited(const Path& path, char delimiter) +{ + std::string name; + + unsigned count = 0; + for(const auto& element : path) + { + if (count == 0) + { + name += element.stem().string(); + } + else + { + name += delimiter + element.stem().string(); + } + count++; + } + + return name; +} diff --git a/src/core/file_utilities/PathUtils.h b/src/core/file_utilities/PathUtils.h new file mode 100644 index 0000000..5c59dea --- /dev/null +++ b/src/core/file_utilities/PathUtils.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include + +using Path = std::filesystem::path; + +class PathUtils +{ +public: + static std::string getBaseFilename(const Path& path); + + static Path getRelativePath(const Path& path, const Path& relativeTo); + + static std::string getPathDelimited(const Path& path, char delimiter='-'); +}; diff --git a/src/web/CMakeLists.txt b/src/web/CMakeLists.txt index e219c9e..14db406 100644 --- a/src/web/CMakeLists.txt +++ b/src/web/CMakeLists.txt @@ -15,6 +15,10 @@ list(APPEND web_LIB_INCLUDES markdown/MarkdownConverter.cpp markdown/MarkdownDocument.h markdown/MarkdownDocument.cpp + markdown/MarkdownComponents.h + markdown/MarkdownComponents.cpp + markdown/MarkdownElement.h + markdown/MarkdownElement.cpp html/HtmlWriter.cpp html/HtmlDocument.cpp html/HtmlElement.cpp diff --git a/src/web/markdown/MarkdownComponents.cpp b/src/web/markdown/MarkdownComponents.cpp new file mode 100644 index 0000000..ca7b739 --- /dev/null +++ b/src/web/markdown/MarkdownComponents.cpp @@ -0,0 +1,122 @@ +#include "MarkdownComponents.h" + +MarkdownTextSpan::Type MarkdownTextSpan::getType() const +{ + return Type::TEXT_SPAN; +} + +MarkdownParagraph::Type MarkdownParagraph::getType() const +{ + return Type::PARAGRAPH; +} + +void MarkdownParagraph::addChild(std::unique_ptr child) +{ + mChildren.push_back(std::move(child)); +} + +std::size_t MarkdownParagraph::getNumChildren() const +{ + return mChildren.size(); +} + +MarkdownInlineElement* MarkdownParagraph::getChild(std::size_t idx) const +{ + return mChildren[idx].get(); +} + +MarkdownBulletItem::Type MarkdownBulletItem::getType() const +{ + return Type::BULLET_ITEM; +} + +MarkdownBulletList::Type MarkdownBulletList::getType() const +{ + return Type::BULLET_LIST; +} + +void MarkdownBulletList::addChild(std::unique_ptr child) +{ + mChildren.push_back(std::move(child)); +} + +std::size_t MarkdownBulletList::getNumChildren() const +{ + return mChildren.size(); +} + +MarkdownBulletItem* MarkdownBulletList::getChild(std::size_t idx) const +{ + return mChildren[idx].get(); +} + +MarkdownHeading::MarkdownHeading(unsigned level) + : mLevel(level) +{ + +} + +MarkdownHeading::Type MarkdownHeading::getType() const +{ + return Type::HEADING; +} + +unsigned MarkdownHeading::getLevel() const +{ + return mLevel; +} + +MarkdownInlineQuote::Type MarkdownInlineQuote::getType() const +{ + return Type::INLINE_QUOTE; +} + +MarkdownLink::MarkdownLink(const std::string& target) + : mTarget(target) +{ + +} + +const std::string& MarkdownLink::getTarget() const +{ + return mTarget; +} + +MarkdownLink::Type MarkdownLink::getType() const +{ + return Type::LINK; +} + + +MarkdownImage::MarkdownImage(const std::string& source, const std::string& alt) + : mSource(source), + mAlt(alt) +{ + +} + +MarkdownImage::Type MarkdownImage::getType() const +{ + return Type::IMAGE; +} + +const std::string& MarkdownImage::getSource() const +{ + return mSource; +} + +const std::string& MarkdownImage::getAlt() const +{ + return mAlt; +} + +MarkdownMultilineQuote::MarkdownMultilineQuote(const std::string& tag) + : mTag(tag) +{ + +} + +MarkdownMultilineQuote::Type MarkdownMultilineQuote::getType() const +{ + return Type::MULTILINE_QUOTE; +} diff --git a/src/web/markdown/MarkdownComponents.h b/src/web/markdown/MarkdownComponents.h new file mode 100644 index 0000000..6b19ddf --- /dev/null +++ b/src/web/markdown/MarkdownComponents.h @@ -0,0 +1,124 @@ +#pragma once + +#include "MarkdownElement.h" + +#include +#include + +class MarkdownTextSpan : public MarkdownInlineElement +{ +public: + virtual ~MarkdownTextSpan() = default; + + Type getType() const override; +}; + +class MarkdownParagraph : public MarkdownElement +{ +public: + virtual ~MarkdownParagraph() = default; + + Type getType() const override; + + void addChild(std::unique_ptr child); + + std::size_t getNumChildren() const; + + MarkdownInlineElement* getChild(std::size_t idx) const; + +private: + std::vector > mChildren; +}; + +class MarkdownBulletItem : public MarkdownElement +{ +public: + virtual ~MarkdownBulletItem() = default; + + Type getType() const override; +}; + +class MarkdownBulletList : public MarkdownElement +{ +public: + virtual ~MarkdownBulletList() = default; + + Type getType() const override; + + void addChild(std::unique_ptr child); + + std::size_t getNumChildren() const; + + MarkdownBulletItem* getChild(std::size_t idx) const; + +private: + std::vector > mChildren; +}; + +class MarkdownHeading : public MarkdownElement +{ +public: + MarkdownHeading(unsigned level); + + virtual ~MarkdownHeading() = default; + + Type getType() const override; + + unsigned getLevel() const; + +private: + unsigned mLevel{1}; +}; + +class MarkdownInlineQuote : public MarkdownInlineElement +{ +public: + + virtual ~MarkdownInlineQuote() = default; + + Type getType() const override; +}; + +class MarkdownLink : public MarkdownInlineElement +{ +public: + MarkdownLink(const std::string& target); + + virtual ~MarkdownLink() = default; + + const std::string& getTarget() const; + + Type getType() const override; +private: + std::string mTarget; +}; + +class MarkdownImage : public MarkdownInlineElement +{ +public: + MarkdownImage(const std::string& source, const std::string& alt); + + virtual ~MarkdownImage() = default; + + Type getType() const override; + + const std::string& getSource() const; + + const std::string& getAlt() const; + +private: + std::string mSource; + std::string mAlt; +}; + +class MarkdownMultilineQuote : public MarkdownElement +{ +public: + MarkdownMultilineQuote(const std::string& tag); + + virtual ~MarkdownMultilineQuote() = default; + + Type getType() const override; +private: + std::string mTag; +}; diff --git a/src/web/markdown/MarkdownConverter.cpp b/src/web/markdown/MarkdownConverter.cpp index b561fee..2a83dc1 100644 --- a/src/web/markdown/MarkdownConverter.cpp +++ b/src/web/markdown/MarkdownConverter.cpp @@ -4,6 +4,8 @@ #include "HtmlElement.h" #include "HtmlParagraphElement.h" #include "HtmlTextRun.h" +#include "MarkdownElement.h" +#include "MarkdownComponents.h" #include "MarkdownDocument.h" diff --git a/src/web/markdown/MarkdownDocument.cpp b/src/web/markdown/MarkdownDocument.cpp index e69de29..2db073a 100644 --- a/src/web/markdown/MarkdownDocument.cpp +++ b/src/web/markdown/MarkdownDocument.cpp @@ -0,0 +1,18 @@ +#include "MarkdownDocument.h" + +#include "MarkdownElement.h" + +void MarkdownDocument::addElement(std::unique_ptr element) +{ + mElements.push_back(std::move(element)); +} + +std::size_t MarkdownDocument::getNumElements() const +{ + return mElements.size(); +} + +MarkdownElement* MarkdownDocument::getElement(std::size_t idx) const +{ + return mElements[idx].get(); +} diff --git a/src/web/markdown/MarkdownDocument.h b/src/web/markdown/MarkdownDocument.h index 549e637..6a02655 100644 --- a/src/web/markdown/MarkdownDocument.h +++ b/src/web/markdown/MarkdownDocument.h @@ -3,262 +3,16 @@ #include #include -class MarkdownElement -{ -public: - enum class Type - { - HEADING, - PARAGRAPH, - TEXT_SPAN, - INLINE_CODE, - MULTILINE_CODE, - INLINE_QUOTE, - MULTILINE_QUOTE, - INLINE_SPECIAL, - MULTILINE_SPECIAL, - LINK, - IMAGE, - BULLET_ITEM, - BULLET_LIST - }; - - virtual ~MarkdownElement() = default; - - void appendTextContent(const std::string& content) - { - mTextContent += content; - } - - const std::string& getTextContent() const - { - return mTextContent; - } - - virtual Type getType() const = 0; -private: - std::string mTextContent; -}; - -class MarkdownInlineElement : public MarkdownElement -{ -public: - virtual ~MarkdownInlineElement() = default; -}; - -class MarkdownTextSpan : public MarkdownInlineElement -{ -public: - virtual ~MarkdownTextSpan() = default; - - Type getType() const override - { - return Type::TEXT_SPAN; - } -}; - -class MarkdownParagraph : public MarkdownElement -{ -public: - virtual ~MarkdownParagraph() = default; - - Type getType() const override - { - return Type::PARAGRAPH; - } - - void addChild(std::unique_ptr child) - { - mChildren.push_back(std::move(child)); - } - - std::size_t getNumChildren() const - { - return mChildren.size(); - } - - MarkdownInlineElement* getChild(std::size_t idx) const - { - return mChildren[idx].get(); - } - - std::vector > mChildren; -}; - -class MarkdownBulletItem : public MarkdownElement -{ -public: - virtual ~MarkdownBulletItem() = default; - - Type getType() const override - { - return Type::BULLET_ITEM; - } -}; - -class MarkdownBulletList : public MarkdownElement -{ -public: - virtual ~MarkdownBulletList() = default; - - Type getType() const override - { - return Type::BULLET_LIST; - } - - void addChild(std::unique_ptr child) - { - mChildren.push_back(std::move(child)); - } - - std::size_t getNumChildren() const - { - return mChildren.size(); - } - - MarkdownBulletItem* getChild(std::size_t idx) const - { - return mChildren[idx].get(); - } - - std::vector > mChildren; -}; - -class MarkdownHeading : public MarkdownElement -{ -public: - MarkdownHeading(unsigned level) - : mLevel(level) - { - - } - virtual ~MarkdownHeading() = default; - - Type getType() const override - { - return Type::HEADING; - } - - unsigned getLevel() const - { - return mLevel; - } - -private: - unsigned mLevel{1}; -}; - - - -class MarkdownInlineQuote : public MarkdownInlineElement -{ -public: - - virtual ~MarkdownInlineQuote() = default; - - Type getType() const override - { - return Type::INLINE_QUOTE; - } -}; - -class MarkdownLink : public MarkdownInlineElement -{ -public: - - MarkdownLink(const std::string& target) - : mTarget(target) - { - - } - - virtual ~MarkdownLink() = default; - - const std::string& getTarget() const - { - return mTarget; - } - - Type getType() const override - { - return Type::LINK; - } -private: - std::string mTarget; -}; - -class MarkdownImage : public MarkdownInlineElement -{ -public: - MarkdownImage(const std::string& source, const std::string& alt) - : mSource(source), - mAlt(alt) - { - - } - - virtual ~MarkdownImage() = default; - - Type getType() const override - { - return Type::IMAGE; - } - - const std::string& getSource() const - { - return mSource; - } - - const std::string& getAlt() const - { - return mAlt; - } - -private: - std::string mSource; - std::string mAlt; -}; - -class MarkdownMultilineQuote : public MarkdownElement -{ -public: - MarkdownMultilineQuote(const std::string& tag) - : mTag(tag) - { - - } - - virtual ~MarkdownMultilineQuote() = default; - - Type getType() const override - { - return Type::MULTILINE_QUOTE; - } - -private: - std::string mTag; -}; - - - +class MarkdownElement; class MarkdownDocument { public: - void addElement(std::unique_ptr element) - { - mElements.push_back(std::move(element)); - } + void addElement(std::unique_ptr element); - std::size_t getNumElements() const - { - return mElements.size(); - } + std::size_t getNumElements() const; - MarkdownElement* getElement(std::size_t idx) const - { - return mElements[idx].get(); - } + MarkdownElement* getElement(std::size_t idx) const; private: std::vector > mElements; diff --git a/src/web/markdown/MarkdownElement.cpp b/src/web/markdown/MarkdownElement.cpp new file mode 100644 index 0000000..ec0d974 --- /dev/null +++ b/src/web/markdown/MarkdownElement.cpp @@ -0,0 +1,11 @@ +#include "MarkdownElement.h" + +void MarkdownElement::appendTextContent(const std::string& content) +{ + mTextContent += content; +} + +const std::string& MarkdownElement::getTextContent() const +{ + return mTextContent; +} diff --git a/src/web/markdown/MarkdownElement.h b/src/web/markdown/MarkdownElement.h new file mode 100644 index 0000000..cb752d1 --- /dev/null +++ b/src/web/markdown/MarkdownElement.h @@ -0,0 +1,40 @@ +#pragma once + +#include + +class MarkdownElement +{ +public: + enum class Type + { + HEADING, + PARAGRAPH, + TEXT_SPAN, + INLINE_CODE, + MULTILINE_CODE, + INLINE_QUOTE, + MULTILINE_QUOTE, + INLINE_SPECIAL, + MULTILINE_SPECIAL, + LINK, + IMAGE, + BULLET_ITEM, + BULLET_LIST + }; + + virtual ~MarkdownElement() = default; + + void appendTextContent(const std::string& content); + + const std::string& getTextContent() const; + + virtual Type getType() const = 0; +private: + std::string mTextContent; +}; + +class MarkdownInlineElement : public MarkdownElement +{ +public: + virtual ~MarkdownInlineElement() = default; +}; diff --git a/src/web/markdown/MarkdownParser.cpp b/src/web/markdown/MarkdownParser.cpp index f05dd77..72912e9 100644 --- a/src/web/markdown/MarkdownParser.cpp +++ b/src/web/markdown/MarkdownParser.cpp @@ -2,6 +2,7 @@ #include "MarkdownDocument.h" #include "StringUtils.h" +#include "MarkdownComponents.h" #include #include