From c0c76f1481498605f7effb5005cfc3b65917e5b6 Mon Sep 17 00:00:00 2001 From: Relintai Date: Mon, 28 Dec 2020 23:17:30 +0100 Subject: [PATCH] Added a PagedArticle class. It goes through a given folder, evaluates all first level subfolders, and creates an article from each directory, and page into those articles from each file with pagination. --- modules/paged_article/SCsub | 12 ++ modules/paged_article/detect.py | 27 +++ modules/paged_article/paged_article.cpp | 210 ++++++++++++++++++++++++ modules/paged_article/paged_article.h | 46 ++++++ 4 files changed, 295 insertions(+) create mode 100644 modules/paged_article/SCsub create mode 100644 modules/paged_article/detect.py create mode 100644 modules/paged_article/paged_article.cpp create mode 100644 modules/paged_article/paged_article.h diff --git a/modules/paged_article/SCsub b/modules/paged_article/SCsub new file mode 100644 index 0000000..510fa70 --- /dev/null +++ b/modules/paged_article/SCsub @@ -0,0 +1,12 @@ +#!/usr/bin/env python + +Import("env_mod") +Import("env") + +env_mod.core_sources = [] + +env_mod.add_source_files(env_mod.core_sources, "*.cpp") + +# Build it all as a library +lib = env_mod.add_library("list_page", env_mod.core_sources) +env.Prepend(LIBS=[lib]) diff --git a/modules/paged_article/detect.py b/modules/paged_article/detect.py new file mode 100644 index 0000000..89d647e --- /dev/null +++ b/modules/paged_article/detect.py @@ -0,0 +1,27 @@ +import os +import platform +import sys + + +def is_active(): + return True + + +def get_name(): + return "list_page" + + +def can_build(): + return True + + +def get_opts(): + return [] + +def get_flags(): + + return [] + + +def configure(env): + pass diff --git a/modules/paged_article/paged_article.cpp b/modules/paged_article/paged_article.cpp new file mode 100644 index 0000000..7a56ffa --- /dev/null +++ b/modules/paged_article/paged_article.cpp @@ -0,0 +1,210 @@ +#include "paged_article.h" + +#include "core/query_builder.h" +#include "core/query_result.h" +#include "core/table_builder.h" +#include "core/utils.h" + +#include +#include + +#include "core/application.h" + +void PagedArticle::index(Request *request) { + const std::string r = request->get_current_path_segment(); + + Article *s = pages[r]; + + if (s == nullptr) { + Application::get_instance()->send_error(404, request); + return; + } + + request->push_path(); + + const std::string rp = request->get_current_path_segment(); + + if (rp == "") { + //summary page + request->body += s->summary_page; + + request->compile_and_send_body(); + request->pop_path(); + return; + } + + const std::string *page = s->pages[rp]; + + if (page == nullptr) { + //bad url + Application::get_instance()->send_error(404, request); + return; + } + + request->body += (*page); + request->compile_and_send_body(); + request->pop_path(); +} + +void PagedArticle::load() { + if (folder == "") { + printf("Error: PagedArticle::load called, but a folder is not set!"); + return; + } + + if (base_path.size() > 0 && base_path[base_path.size() - 1] == '/') { + base_path.pop_back(); + } + + tinydir_dir dir; + if (tinydir_open(&dir, folder.c_str()) == -1) { + printf("Error opening PagedArticle::folder!\n"); + return; + } + + while (dir.has_next) { + tinydir_file file; + if (tinydir_readfile(&dir, &file) == -1) { + tinydir_next(&dir); + continue; + } + + if (file.is_dir) { + if (file.name[0] == '.' || (file.name[0] == '.' && file.name[1] == '.')) { + tinydir_next(&dir); + continue; + } + + std::string np = file.path; + std::string fn = file.name; + + Article *a = load_folder(np, base_path + "/" + fn); + + if (a) { + + std::string p = file.name; + + a->url = p; + pages[p] = a; + } + } + + tinydir_next(&dir); + } + + tinydir_close(&dir); + + generate_summaries(); +} + +Article *PagedArticle::load_folder(const std::string &folder, const std::string &path) { + printf("PagedArticle: loading: %s\n", folder.c_str()); + + std::vector files; + + tinydir_dir dir; + if (tinydir_open(&dir, folder.c_str()) == -1) { + printf("PagedArticle::load_folder: Error opening folder %s!\n", folder.c_str()); + return nullptr; + } + + while (dir.has_next) { + tinydir_file file; + if (tinydir_readfile(&dir, &file) == -1) { + tinydir_next(&dir); + continue; + } + + if (!file.is_dir) { + std::string np = file.name; + + files.push_back(np); + } + + tinydir_next(&dir); + } + + tinydir_close(&dir); + + if (files.size() == 0) { + return nullptr; + } + + std::sort(files.begin(), files.end()); + + Article *article = new Article(); + + for (uint32_t i = 0; i < files.size(); ++i) { + std::string file_path = folder; + + if (file_path.size() > 0 && file_path[file_path.size() - 1] != '/') + file_path += "/"; + + file_path += files[i].c_str(); + + FILE *f = fopen(file_path.c_str(), "r"); + + if (!f) { + printf("PagedArticle::load_folder: Error opening file! %s\n", file_path.c_str()); + continue; + } + + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); /* same as rewind(f); */ + + std::string fd; + fd.resize(fsize); + + fread(&fd[0], 1, fsize, f); + fclose(f); + + Utils::markdown_to_html(&fd); + + std::string pagination; + + pagination = Utils::get_pagination_links(path, files, i); + + std::string *finals = new std::string(); + + (*finals) += pagination; + (*finals) += fd; + (*finals) += pagination; + + article->pages[files[i]] = finals; + + if (i == 0) { + article->summary_page = (*finals); + } + } + + return article; +} + +void PagedArticle::generate_summaries() { + for (std::map::iterator it = pages.begin(); it != pages.end(); ++it) { + generate_summary((*it).second); + } +} + +void PagedArticle::generate_summary(Article *article) { + if (article->summary_page != "") { + return; + } + + for (std::map::iterator it = article->pages.begin(); it != article->pages.end(); ++it) { + std::string *s = (*it).second; + + if (s != nullptr) { + article->summary_page = (*s); + } + } +} + +PagedArticle::PagedArticle() : + Object() { +} + +PagedArticle::~PagedArticle() { + pages.clear(); +} \ No newline at end of file diff --git a/modules/paged_article/paged_article.h b/modules/paged_article/paged_article.h new file mode 100644 index 0000000..f4d9db4 --- /dev/null +++ b/modules/paged_article/paged_article.h @@ -0,0 +1,46 @@ +#ifndef PAGED_ARTICLE_H +#define PAGED_ARTICLE_H + +#include +#include +#include + +#include "core/object.h" + +#include "core/request.h" + +struct Article { + std::string url; + std::string summary_page; + std::map pages; + + Article() {} + ~Article() { + for (std::map::iterator it = pages.begin(); it != pages.end(); ++it) { + delete ((*it).second); + } + + pages.clear(); + } +}; + +class PagedArticle : public Object { + RCPP_OBJECT(PagedArticle, Object); + +public: + void index(Request *request); + + void load(); + Article *load_folder(const std::string &folder, const std::string &path); + void generate_summaries(); + void generate_summary(Article *article); + + PagedArticle(); + ~PagedArticle(); + + std::map pages; + std::string folder; + std::string base_path; +}; + +#endif \ No newline at end of file