From 8796199757156e5fb98d7a27e31145f1c3bb62dd Mon Sep 17 00:00:00 2001 From: Szymon P Date: Mon, 12 Jan 2026 10:41:50 +0100 Subject: [PATCH 1/3] added format_file() function --- src/format/format.cpp | 19 +++++++++++++++++++ src/format/format.hpp | 12 +++++++----- src/tests.cpp | 23 +++++++++++++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) diff --git a/src/format/format.cpp b/src/format/format.cpp index 68516de..c7f867f 100644 --- a/src/format/format.cpp +++ b/src/format/format.cpp @@ -1,4 +1,6 @@ +#include "format/format.hpp" #include "markdown/markdown.hpp" +#include #include static bool replace_once(std::string &str, const std::string &from, @@ -9,3 +11,20 @@ static bool replace_once(std::string &str, const std::string &from, str.replace(start_pos, from.length(), to); return true; } + +std::string format_file(const std::string &TEMPLATE_FILE, + const std::string &TEMPLATE, const std::string &INPUT) { + bool is_template = TEMPLATE_FILE.find(TEMPLATE) != std::string::npos; + std::string result = TEMPLATE_FILE; + + if (!is_template) { + std::clog << "There is no template in given file. Is this correct?" + << std::endl; + return result; + } + + while (is_template) { + is_template = replace_once(result, TEMPLATE, INPUT); + } + return result; +} diff --git a/src/format/format.hpp b/src/format/format.hpp index ee70c95..efa9f2b 100644 --- a/src/format/format.hpp +++ b/src/format/format.hpp @@ -1,7 +1,9 @@ #include -// Change template from file into html -// Return html in string -std::string inject_html_into_template(const std::string &FILE_NAME, - const std::string &TEMPLATE, - const std::string &HTML); +// @brief Format file. +// @param TEMPLATE_FILE File that you want to format in string. +// @param TEMPLATE Template that you want to replace. For example `{{title}}` +// @param INPUT Text that you want to replace TEMPLATE with. +// @return Formatted file in std::string +std::string format_file(const std::string &TEMPLATE_FILE, + const std::string &TEMPLATE, const std::string &INPUT); diff --git a/src/tests.cpp b/src/tests.cpp index e13575e..8f82fde 100644 --- a/src/tests.cpp +++ b/src/tests.cpp @@ -31,6 +31,18 @@ constexpr const char *formatter_html = R"( )"; +constexpr const char *formated_html = R"( + + + + + Document + + + I'm formatted! + +)"; + constexpr const char *no_metadata_post_md = R"(# This markdown has no metadata. That's bad. Don't do it. It's for tests only.)"; @@ -88,6 +100,8 @@ TEST_CASE("Test reading a file that doesn't exist") { REQUIRE_THROWS(read_file("this/path/doesnt/exist")); } +// Config tests + TEST_CASE("Checking config file read", "[config]") { Config config = get_config(TestFiles::config_toml); @@ -98,6 +112,8 @@ TEST_CASE("Checking config file read", "[config]") { REQUIRE(config.general.title == "Blog"); } +// Markdown tests + TEST_CASE("get_metadata function data correctness test") { Metadata result = get_metadata(TestFiles::post_md).value(); @@ -160,3 +176,10 @@ int main() { REQUIRE(get_html(TestFiles::post_md) == EXPECTED_OUTPUT); } + +// Format tests +TEST_CASE("Test format_file function with correct data") { + REQUIRE(TestFiles::formated_html == format_file(TestFiles::formatter_html, + "{{replace_me}}", + "I'm formatted!")); +} From 1a58577b3eb1410981410e26ce26cdd3283e81c6 Mon Sep 17 00:00:00 2001 From: Szymon P Date: Mon, 12 Jan 2026 11:18:03 +0100 Subject: [PATCH 2/3] added format_file_conditionally() --- src/format/format.cpp | 72 +++++++++++++++++++++++++++++++++++++++---- src/format/format.hpp | 10 ++++++ 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/src/format/format.cpp b/src/format/format.cpp index c7f867f..afb99f8 100644 --- a/src/format/format.cpp +++ b/src/format/format.cpp @@ -3,12 +3,43 @@ #include #include -static bool replace_once(std::string &str, const std::string &from, - const std::string &to) { - size_t start_pos = str.find(from); - if (start_pos == std::string::npos) +// Replace TEMPLATE with REPLACMENT in-place +static bool replace_once_global(std::string &STR, const std::string &TEMPLATE, + const std::string &REPLACMENT) { + size_t start_pos = STR.find(TEMPLATE); + if (start_pos == std::string::npos) { return false; - str.replace(start_pos, from.length(), to); + } + STR.replace(start_pos, TEMPLATE.length(), REPLACMENT); + return true; +} + +// Replace TEMPLATE with REPLACMENT between starting from `start` +static bool replace_once_between(std::string &STR, const std::string &TEMPLATE, + const std::string &REPLACMENT, + const size_t &START) { + size_t start_pos = STR.find(TEMPLATE, START); + if (start_pos == std::string::npos) { + return false; + } + STR.replace(start_pos, TEMPLATE.length(), REPLACMENT); + return true; +} + +// Remove everything from START to STOP +static bool remove_from_to(std::string &STR, const std::string &START, + const std::string &STOP) { + size_t start_pos = STR.find(START); + if (start_pos == std::string::npos) { + return false; + } + + size_t stop_pos = STR.find(STOP, start_pos); + if (stop_pos == std::string::npos) { + return false; + } + + STR.replace(start_pos, stop_pos - start_pos + STOP.length(), ""); return true; } @@ -24,7 +55,36 @@ std::string format_file(const std::string &TEMPLATE_FILE, } while (is_template) { - is_template = replace_once(result, TEMPLATE, INPUT); + is_template = replace_once_global(result, TEMPLATE, INPUT); + } + return result; +} + +std::string format_file_condtionally(const std::string &TEMPLATE_FILE, + const std::string &TEMPLATE, + const std::string &INPUT) { + + size_t template_pos = TEMPLATE_FILE.find(TEMPLATE); + bool is_template = template_pos != std::string::npos; + + std::string result = TEMPLATE_FILE; + + if (!is_template) { + std::clog << "There is no template in given file. Is this correct?" + << std::endl; + return result; + } + + // if template is empty then we remove everything in between + if (TEMPLATE == "") { + while (is_template) { + is_template = remove_from_to(result, TEMPLATE, "{{endif}"); + } + } + + while (is_template) { + is_template = + replace_once_between(result, TEMPLATE, INPUT, result.find(TEMPLATE)); } return result; } diff --git a/src/format/format.hpp b/src/format/format.hpp index efa9f2b..8f04037 100644 --- a/src/format/format.hpp +++ b/src/format/format.hpp @@ -7,3 +7,13 @@ // @return Formatted file in std::string std::string format_file(const std::string &TEMPLATE_FILE, const std::string &TEMPLATE, const std::string &INPUT); + +// @brief Format file conditionally. Replace everything between `{{if +// _something_}}` to `{{endif}}` If INPUT is empty then everything between +// this will be removed. +// @param TEMPLATE_FILE File that you want to format in string. +// @param TEMPLATE Full name of the if statement. For example `{{if title}}` +// @return Formatted file in std::string +std::string format_file_condtionally(const std::string &TEMPLATE_FILE, + const std::string &TEMPLATE, + const std::string &INPUT); From 19d86e8dc7d057481055e3d98d1e9fa0b322f0d0 Mon Sep 17 00:00:00 2001 From: Szymon P Date: Mon, 12 Jan 2026 12:52:19 +0100 Subject: [PATCH 3/3] made formatting files work --- src/format/format.cpp | 99 +++++++++++++++++-------------------------- src/format/format.hpp | 8 ++-- src/tests.cpp | 58 +++++++++++++++++++++++++ 3 files changed, 103 insertions(+), 62 deletions(-) diff --git a/src/format/format.cpp b/src/format/format.cpp index afb99f8..1be57dc 100644 --- a/src/format/format.cpp +++ b/src/format/format.cpp @@ -1,31 +1,7 @@ #include "format/format.hpp" #include "markdown/markdown.hpp" -#include #include -// Replace TEMPLATE with REPLACMENT in-place -static bool replace_once_global(std::string &STR, const std::string &TEMPLATE, - const std::string &REPLACMENT) { - size_t start_pos = STR.find(TEMPLATE); - if (start_pos == std::string::npos) { - return false; - } - STR.replace(start_pos, TEMPLATE.length(), REPLACMENT); - return true; -} - -// Replace TEMPLATE with REPLACMENT between starting from `start` -static bool replace_once_between(std::string &STR, const std::string &TEMPLATE, - const std::string &REPLACMENT, - const size_t &START) { - size_t start_pos = STR.find(TEMPLATE, START); - if (start_pos == std::string::npos) { - return false; - } - STR.replace(start_pos, TEMPLATE.length(), REPLACMENT); - return true; -} - // Remove everything from START to STOP static bool remove_from_to(std::string &STR, const std::string &START, const std::string &STOP) { @@ -45,46 +21,51 @@ static bool remove_from_to(std::string &STR, const std::string &START, std::string format_file(const std::string &TEMPLATE_FILE, const std::string &TEMPLATE, const std::string &INPUT) { - bool is_template = TEMPLATE_FILE.find(TEMPLATE) != std::string::npos; std::string result = TEMPLATE_FILE; + size_t current_pos = 0; - if (!is_template) { - std::clog << "There is no template in given file. Is this correct?" - << std::endl; - return result; - } + while (true) { + size_t found_pos = result.find(TEMPLATE, current_pos); - while (is_template) { - is_template = replace_once_global(result, TEMPLATE, INPUT); - } - return result; -} - -std::string format_file_condtionally(const std::string &TEMPLATE_FILE, - const std::string &TEMPLATE, - const std::string &INPUT) { - - size_t template_pos = TEMPLATE_FILE.find(TEMPLATE); - bool is_template = template_pos != std::string::npos; - - std::string result = TEMPLATE_FILE; - - if (!is_template) { - std::clog << "There is no template in given file. Is this correct?" - << std::endl; - return result; - } - - // if template is empty then we remove everything in between - if (TEMPLATE == "") { - while (is_template) { - is_template = remove_from_to(result, TEMPLATE, "{{endif}"); + if (found_pos == std::string::npos) { + break; } - } - while (is_template) { - is_template = - replace_once_between(result, TEMPLATE, INPUT, result.find(TEMPLATE)); + result.replace(found_pos, TEMPLATE.length(), INPUT); + current_pos = found_pos + INPUT.length(); } return result; } + +std::string format_file_conditionally(const std::string &TEMPLATE_FILE, + const std::string &START_TAG, + const std::string &END_TAG, + const std::string &TEMPLATE, + const std::string &INPUT) { + std::string result = TEMPLATE_FILE; + + if (INPUT.empty()) { + while (true) { + if (!remove_from_to(result, START_TAG, END_TAG)) { + break; + } + } + } else { + // remove START tag + size_t pos = 0; + while ((pos = result.find(START_TAG, pos)) != std::string::npos) { + result.replace(pos, START_TAG.length(), ""); + } + + // remove END tag + pos = 0; + while ((pos = result.find(END_TAG, pos)) != std::string::npos) { + result.replace(pos, END_TAG.length(), ""); + } + + // replace + result = format_file(result, TEMPLATE, INPUT); + } + + return result; +} diff --git a/src/format/format.hpp b/src/format/format.hpp index 8f04037..78bf316 100644 --- a/src/format/format.hpp +++ b/src/format/format.hpp @@ -14,6 +14,8 @@ std::string format_file(const std::string &TEMPLATE_FILE, // @param TEMPLATE_FILE File that you want to format in string. // @param TEMPLATE Full name of the if statement. For example `{{if title}}` // @return Formatted file in std::string -std::string format_file_condtionally(const std::string &TEMPLATE_FILE, - const std::string &TEMPLATE, - const std::string &INPUT); +std::string format_file_conditionally(const std::string &TEMPLATE_FILE, + const std::string &START_TAG, + const std::string &END_TAG, + const std::string &TEMPLATE, + const std::string &INPUT); diff --git a/src/tests.cpp b/src/tests.cpp index 8f82fde..c2bc76d 100644 --- a/src/tests.cpp +++ b/src/tests.cpp @@ -43,6 +43,46 @@ constexpr const char *formated_html = R"( )"; +constexpr const char *formatter_html_conditionally = R"( + + + + + Document + + +{{if tag}} +

{{tag}}

+{{endif}} + +)"; + +constexpr const char *formated_html_conditionally = R"( + + + + + Document + + + +

tag

+ + +)"; + +constexpr const char *formated_html_conditionally_empty = R"( + + + + + Document + + + + +)"; + constexpr const char *no_metadata_post_md = R"(# This markdown has no metadata. That's bad. Don't do it. It's for tests only.)"; @@ -183,3 +223,21 @@ TEST_CASE("Test format_file function with correct data") { "{{replace_me}}", "I'm formatted!")); } + +TEST_CASE("Test format_file function with no templates") { + REQUIRE(TestFiles::formated_html == + format_file(TestFiles::formated_html, "{{replace_me}}", "nothing")); +} + +TEST_CASE("Test format_file_conditionally with tag") { + REQUIRE(TestFiles::formated_html_conditionally == + format_file_conditionally(TestFiles::formatter_html_conditionally, + "{{if tag}}", "{{endif}}", "{{tag}}", + "tag")); +} + +TEST_CASE("Test format_file_conditionally with empty tag") { + REQUIRE(TestFiles::formated_html_conditionally_empty == + format_file_conditionally(TestFiles::formatter_html_conditionally, + "{{if tag}}", "{{endif}}", "{{tag}}", "")); +}