aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2021-10-23 01:44:37 +0200
committerToni Uhlig <matzeton@googlemail.com>2021-10-23 01:44:37 +0200
commitca7ca2218e07a24075cdc9d48e967cfdc2a3543b (patch)
tree69d0c5d6c0d064770a04b07faf005bc4fbbe7757
parent09f45879c2b2e63689265924cb700dee5f02f653 (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.hpp2
-rw-r--r--src/ContentManager.cpp11
-rw-r--r--src/EventManager.cpp6
-rw-r--r--src/RequestResponse.cpp7
-rw-r--r--src/TemplateManager.cpp69
-rw-r--r--src/TemplateManager.hpp2
-rw-r--r--src/content/blog/Blog.cpp63
-rw-r--r--src/content/blog/Blog.hpp6
-rw-r--r--src/content/markdown/Markdown.cpp56
-rw-r--r--src/content/markdown/Markdown.hpp1
-rw-r--r--wwwroot/blog/index.html2
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>