diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2021-10-23 01:44:37 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2021-10-23 01:44:37 +0200 |
commit | ca7ca2218e07a24075cdc9d48e967cfdc2a3543b (patch) | |
tree | 69d0c5d6c0d064770a04b07faf005bc4fbbe7757 | |
parent | 09f45879c2b2e63689265924cb700dee5f02f653 (diff) |
Improved Blog/Markdown URI base path handling.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | deps/inja/single_include/inja/inja.hpp | 2 | ||||
-rw-r--r-- | src/ContentManager.cpp | 11 | ||||
-rw-r--r-- | src/EventManager.cpp | 6 | ||||
-rw-r--r-- | src/RequestResponse.cpp | 7 | ||||
-rw-r--r-- | src/TemplateManager.cpp | 69 | ||||
-rw-r--r-- | src/TemplateManager.hpp | 2 | ||||
-rw-r--r-- | src/content/blog/Blog.cpp | 63 | ||||
-rw-r--r-- | src/content/blog/Blog.hpp | 6 | ||||
-rw-r--r-- | src/content/markdown/Markdown.cpp | 56 | ||||
-rw-r--r-- | src/content/markdown/Markdown.hpp | 1 | ||||
-rw-r--r-- | wwwroot/blog/index.html | 2 |
11 files changed, 123 insertions, 102 deletions
diff --git a/deps/inja/single_include/inja/inja.hpp b/deps/inja/single_include/inja/inja.hpp index 42dea1c..85cecbc 100644 --- a/deps/inja/single_include/inja/inja.hpp +++ b/deps/inja/single_include/inja/inja.hpp @@ -4129,6 +4129,8 @@ public: void include_template(const std::string &name, const Template &tmpl) { template_storage[name] = tmpl; } + + TemplateStorage & GetTemplateStorage() { return template_storage; } }; /*! diff --git a/src/ContentManager.cpp b/src/ContentManager.cpp index da1ab65..d73122a 100644 --- a/src/ContentManager.cpp +++ b/src/ContentManager.cpp @@ -19,6 +19,11 @@ bool ContentManager::RegisterModule(std::shared_ptr<Content> ctnt) #endif m_ContentModules[basePath] = ctnt; + if (basePath.back() == '/') + { + basePath.pop_back(); + } + return true; } @@ -53,12 +58,6 @@ bool ContentManager::InitAll(void) } m_ContentModulesRoutes[redirect] = content.second; } - - std::string & basePath = content.second->GetUriBasePath(); - if (basePath.back() == '/') - { - basePath.pop_back(); - } } return ret; diff --git a/src/EventManager.cpp b/src/EventManager.cpp index 81b949d..4ca377a 100644 --- a/src/EventManager.cpp +++ b/src/EventManager.cpp @@ -112,7 +112,8 @@ static inline void default_evhttp_callback(struct evhttp_request * const req, Ev struct evbuffer * const output = evbuffer_new(); if (output != nullptr) { - static char const * const page_404 = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" + static char const * const page_404 = + "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n" "<html>\n" "\t<head><title>404 Not Found</title></head>\n" "\t<body><h1>Not Found</h1>The requested URI was not found.</body>\n" @@ -190,7 +191,8 @@ bool EventManager::Init(std::string host, uint16_t port) } for (auto & cm : m_ContentManager->GetAllModulesRoutes()) { - if (evhttp_set_cb(m_EvHttp, cm.first.c_str(), EvContentManagerInterceptor, &m_ContentManager) != 0) + if (evhttp_set_cb(m_EvHttp, cm.first.c_str(), EvContentManagerInterceptor, &m_ContentManager) != 0 && + cm.first != "/") { fprintf(stderr, "Failed to add route callback: %s\n", cm.first.c_str()); } diff --git a/src/RequestResponse.cpp b/src/RequestResponse.cpp index 535de78..59303a8 100644 --- a/src/RequestResponse.cpp +++ b/src/RequestResponse.cpp @@ -28,11 +28,8 @@ bool RequestResponse::UseUri() return false; } char const * const query = evhttp_uri_get_query(uri); - if (query == nullptr) - { - return false; - } - return evhttp_parse_query_str(query, &m_Query) == 0; + evhttp_parse_query_str(query, &m_Query); + return true; } bool RequestResponse::AddOutputHeaderByRef(std::string const & key, std::string const & value) diff --git a/src/TemplateManager.cpp b/src/TemplateManager.cpp index 1e027f2..62b4e27 100644 --- a/src/TemplateManager.cpp +++ b/src/TemplateManager.cpp @@ -4,45 +4,36 @@ TemplateManager::TemplateManager() { - AddInjaCallback("test_fn", - 0, - [](inja::Arguments & args) - { - (void)args; - return "Just a test fn."; - }); - AddInjaCallback("test_return_true", - 0, - [](inja::Arguments & args) - { - (void)args; - return true; - }); + AddInjaCallback("test_fn", 0, [](inja::Arguments & args) { + (void)args; + return "Just a test fn."; + }); + AddInjaCallback("test_return_true", 0, [](inja::Arguments & args) { + (void)args; + return true; + }); /* * indent(input: str, width: int, first: bool, blank: bool); */ - AddInjaCallback("indent", - 4, - [](inja::Arguments & args) - { - std::stringstream stream(args.at(0)->get<std::string>()); - std::string line, out; - bool is_first_line = true; - while (std::getline(stream, line)) - { - if (is_first_line == false || args.at(2)->get<bool>() == true) - { - if (line != "" || args.at(3)->get<bool>() == false) - { - line.insert(0, args.at(1)->get<std::size_t>(), ' '); - } - } - line += '\n'; - out += line; - is_first_line = false; - } - return out; - }); + AddInjaCallback("indent", 4, [](inja::Arguments & args) { + std::stringstream stream(args.at(0)->get<std::string>()); + std::string line, out; + bool is_first_line = true; + while (std::getline(stream, line)) + { + if (is_first_line == false || args.at(2)->get<bool>() == true) + { + if (line != "" || args.at(3)->get<bool>() == false) + { + line.insert(0, args.at(1)->get<std::size_t>(), ' '); + } + } + line += '\n'; + out += line; + is_first_line = false; + } + return out; + }); } void TemplateManager::ParseTemplates(Filesystem & fs) @@ -50,7 +41,7 @@ void TemplateManager::ParseTemplates(Filesystem & fs) for (auto & tpl : fs.GetFiles()) { std::string tmpl(tpl.second.data.data(), tpl.second.data.data() + tpl.second.data.size()); - m_Templates[tpl.first] = m_Inja.parse(tmpl); + m_Inja.include_template(tpl.first, m_Inja.parse(tmpl)); std::cout << "File: " << tpl.first << " may contain a renderable template." << std::endl; } } @@ -71,7 +62,7 @@ void TemplateManager::AddVoidInjaCallback(std::string functionName, bool TemplateManager::TemplateExists(std::string const & templatePath) { - return m_Templates.find(templatePath) != m_Templates.end(); + return m_Inja.GetTemplateStorage().find(templatePath) != m_Inja.GetTemplateStorage().end(); } bool TemplateManager::RenderTemplate(std::string const & templatePath, RenderData const & rd, std::string & out) @@ -83,7 +74,7 @@ bool TemplateManager::RenderTemplate(std::string const & templatePath, RenderDat try { - out = m_Inja.render(m_Templates[templatePath].content, rd); + out = m_Inja.render(m_Inja.GetTemplateStorage()[templatePath].content, rd); } catch (inja::RenderError & re) { diff --git a/src/TemplateManager.hpp b/src/TemplateManager.hpp index 1d98c50..0a2d626 100644 --- a/src/TemplateManager.hpp +++ b/src/TemplateManager.hpp @@ -3,6 +3,7 @@ #include "Content.hpp" #include "Filesystem.hpp" +#include "RequestResponse.hpp" #include <inja/inja.hpp> @@ -21,7 +22,6 @@ public: bool RenderTemplate(std::string const & templatePath, RenderData const & rd, std::string & out); private: - inja::TemplateStorage m_Templates; inja::Environment m_Inja; }; diff --git a/src/content/blog/Blog.cpp b/src/content/blog/Blog.cpp index a472b97..5eb126f 100644 --- a/src/content/blog/Blog.cpp +++ b/src/content/blog/Blog.cpp @@ -1,5 +1,7 @@ #include "Blog.hpp" +#include "../../ContentManager.hpp" + #include <filesystem> Blog::Blog(std::string uriBasePath, std::string blogPath, std::string mainTemplatePath) @@ -29,10 +31,11 @@ bool Blog::Init() for (auto const & jfile : fs.GetFiles()) { + std::string full_uri_path = m_UriBasePath + "/" + std::string(std::filesystem::path(jfile.first).stem()); + ContentManager::RemoveGarbageSlashes(full_uri_path); + auto const json_metadata = inja::json::parse(jfile.second.data); - BlogEntry be = - std::make_shared<struct blog_entry>(jfile.first, - std::string(std::filesystem::path(jfile.first).stem()) + ".md"); + BlogEntry be = std::make_shared<struct blog_entry>(full_uri_path); if (Blog::ValidateAndSetMetdadata(json_metadata, be) == false) { std::cerr << "Blog Metadata validation failed." << std::endl; @@ -40,13 +43,13 @@ bool Blog::Init() } m_BlogEntriesSortedByDate.push_back(be); - m_Redirections.push_back(m_UriBasePath + "/" + std::string(std::filesystem::path(jfile.first).stem())); + m_Redirections.push_back(full_uri_path); } - std::sort(m_BlogEntriesSortedByDate.begin(), - m_BlogEntriesSortedByDate.end(), - [](auto const & a, auto const & b) { return a->publishDate > b->publishDate; }); + std::sort(m_BlogEntriesSortedByDate.begin(), m_BlogEntriesSortedByDate.end(), [](auto const & a, auto const & b) { + return a->publishDate > b->publishDate; + }); - m_BlogContents.Init(); + m_BlogContents.Init(m_UriBasePath); if (retval == false) { @@ -76,7 +79,7 @@ bool Blog::Render(RequestResponse & rr, RenderData & rd, std::string & out) } else { - rd["blog_content"] = "bla"; + return false; } return true; @@ -101,19 +104,17 @@ bool Blog::ValidateAndSetMetdadata(BlogMetadata const & blogMetadata, BlogEntry { bool retval = true; std::function<bool(BlogMetadata const &, std::string const)> validateMetadata = - [blogEntry](BlogMetadata const & bm, std::string const tname) - { - if (bm.find(tname) == bm.cend()) - { - std::cerr << "Metadata validation: JSON key '" << tname << "' missing in " << blogEntry->metadata_filename - << std::endl; - return false; - } - return true; - }; - std::function<bool(std::string const &, std::time_t &)> parseDateTime = - [](std::string const & timeStr, std::time_t & time) - { + [blogEntry](BlogMetadata const & bm, std::string const tname) { + if (bm.find(tname) == bm.cend()) + { + std::cerr << "Metadata validation: JSON key '" << tname << "' missing in " + << blogEntry->filename + ".json" << std::endl; + return false; + } + return true; + }; + std::function<bool(std::string const &, std::time_t &)> parseDateTime = [](std::string const & timeStr, + std::time_t & time) { std::tm tm = {}; std::stringstream ss(timeStr); ss >> std::get_time(&tm, "%d.%m.%y %H:%M"); @@ -175,10 +176,10 @@ bool Blog::ValidateEntries() const for (auto const & e : m_BlogEntriesSortedByDate) { - if (m_BlogContents.HasMarkdownFile(e->content_filename) == false) + if (m_BlogContents.HasMarkdownFile(e->filename) == false) { - std::cerr << "Blog entry metadata " << e->metadata_filename << " exists, but markdown file " - << e->content_filename << " not." << std::endl; + std::cerr << "Blog entry metadata " << e->filename << ".json exists, but markdown file " << e->filename + << ".md not." << std::endl; retval = false; } } @@ -186,9 +187,10 @@ bool Blog::ValidateEntries() const { if (std::any_of(m_BlogEntriesSortedByDate.cbegin(), m_BlogEntriesSortedByDate.cend(), - [m](BlogEntry const & be) { return m.first == be->content_filename; }) == false) + [m](BlogEntry const & be) { return m.first == be->filename; }) == false) { - std::cerr << "Blog entry markdown " << m.first << " exists, but metadata not." << std::endl; + std::cerr << "Blog entry markdown " << m.first << ".md exists, but metadata " << m.first << ".json not." + << std::endl; retval = false; } } @@ -206,17 +208,16 @@ void Blog::GenerateBlogListing(RenderData & rd) } RenderData re; - re["metadata_filename"] = e->metadata_filename; - re["content_filename"] = e->content_filename; + re["filename"] = e->filename; re["title"] = e->title; re["tags"] = e->tags; re["author"] = e->author; re["createDate"] = e->createDate; re["publishDate"] = e->publishDate; re["published"] = e->published; - if (m_BlogContents.HasMarkdownFile(e->content_filename) == true) + if (m_BlogContents.HasMarkdownFile(e->filename) == true) { - re["content"] = m_BlogContents.GetMarkdownHTML(e->content_filename)->c_str(); + re["content"] = m_BlogContents.GetMarkdownHTML(e->filename)->c_str(); } else { diff --git a/src/content/blog/Blog.hpp b/src/content/blog/Blog.hpp index 06f279c..79c06a2 100644 --- a/src/content/blog/Blog.hpp +++ b/src/content/blog/Blog.hpp @@ -9,13 +9,11 @@ struct blog_entry { - explicit blog_entry(std::string const & metadata_filename, std::string const & content_filename) - : metadata_filename(metadata_filename), content_filename(content_filename) + explicit blog_entry(std::string const & filename) : filename(filename) { } - std::string const metadata_filename; - std::string const content_filename; + std::string const filename; std::string title; std::vector<std::string> tags; diff --git a/src/content/markdown/Markdown.cpp b/src/content/markdown/Markdown.cpp index 2b0bcc6..de05080 100644 --- a/src/content/markdown/Markdown.cpp +++ b/src/content/markdown/Markdown.cpp @@ -1,7 +1,11 @@ #include "Markdown.hpp" +#include "../../ContentManager.hpp" + #include <md4c-html.h> +#include <filesystem> + Markdown::Markdown(std::string uriBasePath, std::string markdownFilesPath, std::string mainTemplatePath) : Content(), m_UriBasePath(uriBasePath), @@ -22,6 +26,12 @@ extern "C" void markdown_to_html_conversion(const MD_CHAR * const text, MD_SIZE html->append(text, size); } +bool Markdown::Init(std::string const & uriBasePath) +{ + m_UriBasePath = uriBasePath; + return Init(); +} + bool Markdown::Init() { std::cout << "Markdown files path: " << m_MarkdownFilesPath << std::endl; @@ -60,7 +70,10 @@ bool Markdown::Init() return false; } - m_Markdowns[mfile.first] = std::make_shared<std::string>(html); + std::string full_uri_path = m_UriBasePath + "/" + std::string(std::filesystem::path(mfile.first).stem()); + ContentManager::RemoveGarbageSlashes(full_uri_path); + m_Markdowns[full_uri_path] = std::make_shared<std::string>(html); + m_Redirections.push_back(full_uri_path); } return true; @@ -84,35 +97,52 @@ bool Markdown::Render(RequestResponse & rr, RenderData & rd, std::string & out) return false; } + if (rr.UseUri() == false) + { + return false; + } + + rd["uri"] = rr.GetUriPath(); + if (rr.GetUriPath() == m_UriBasePath || rr.GetUriPath() == m_UriBasePath + "/" || rr.GetUriPath() == m_UriBasePath + "/index.html") { - rr.UseUri(); std::string requested_markdown; - rd["uri"] = rr.GetUriPath(); if (rr.GetQueryValue("get", requested_markdown) == true) { - requested_markdown += ".md"; - if (HasMarkdownFile(requested_markdown) == true) + if (HasMarkdownFile(m_UriBasePath + "/" + requested_markdown) == true) + { + rd["content"] = *GetMarkdownHTML(m_UriBasePath + "/" + requested_markdown); + } + else if (HasMarkdownFile(m_UriBasePath + "/index.md") == true) + { + rd["content"] = *GetMarkdownHTML(m_UriBasePath + "/index.md"); + } + else { - rd["content"] = *GetMarkdownHTML(requested_markdown); - } else if (HasMarkdownFile("index.md") == true) { - rd["content"] = *GetMarkdownHTML("index.md"); - } else { return false; } } - else if (HasMarkdownFile("index.md") == true) + else if (HasMarkdownFile(m_UriBasePath + "/index") == true) + { + rd["content"] = *GetMarkdownHTML(m_UriBasePath + "/index"); + } + else { - rd["content"] = *GetMarkdownHTML("index.md"); - } else { return false; } } else { - return false; + if (HasMarkdownFile(rr.GetUriPath()) == true) + { + rd["content"] = *GetMarkdownHTML(rr.GetUriPath()); + } + else + { + return false; + } } return true; diff --git a/src/content/markdown/Markdown.hpp b/src/content/markdown/Markdown.hpp index fa14b3a..fe0d968 100644 --- a/src/content/markdown/Markdown.hpp +++ b/src/content/markdown/Markdown.hpp @@ -11,6 +11,7 @@ class Markdown : public Content public: explicit Markdown(std::string uriBasePath, std::string markdownFilesPath, std::string mainTemplatePath = ""); + bool Init(std::string const & uriBasePath); bool Init(); void Shutdown(); bool Render(RequestResponse & rr, RenderData & rd, std::string & out); diff --git a/wwwroot/blog/index.html b/wwwroot/blog/index.html index 554a952..9198152 100644 --- a/wwwroot/blog/index.html +++ b/wwwroot/blog/index.html @@ -8,7 +8,7 @@ Test RetFN.: <b>{{ test_return_true }}</b><br><br><br> ## for entry in blog_listing <tr> <td>{{ loop.index1 }}</td> - <td>{{ entry.content_filename }}</td> + <td>{{ entry.filename }}</td> <td>{{ entry.title }}</td> <td>{{ entry.tags }}</td> <td>{{ entry.author }}</td> |