diff options
| -rw-r--r-- | CMakeLists.txt | 62 | ||||
| -rw-r--r-- | README.md | 26 | ||||
| -rw-r--r-- | config.toml | 3 | ||||
| -rw-r--r-- | src/main.cpp | 102 |
4 files changed, 193 insertions, 0 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..496b2cd --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,62 @@ +cmake_minimum_required(VERSION 3.20) +project(ahsi VERSION 0.1.0 LANGUAGES CXX C) + +set(CMAKE_CXX_STANDARD 20) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + +include(FetchContent) + +FetchContent_Declare( + tomlplusplus + GIT_REPOSITORY https://github.com/marzer/tomlplusplus.git + GIT_TAG v3.4.0 +) +FetchContent_MakeAvailable(tomlplusplus) + +FetchContent_Declare( + json + GIT_REPOSITORY https://github.com/nlohmann/json.git + GIT_TAG v3.11.3 +) +FetchContent_MakeAvailable(json) + +FetchContent_Declare( + inja + GIT_REPOSITORY https://github.com/pantor/inja.git + GIT_TAG v3.4.0 +) + +set(INJA_USE_EMBEDDED_JSON OFF CACHE BOOL "" FORCE) +set(INJA_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(BUILD_TESTING OFF CACHE BOOL "" FORCE) +set(BUILD_BENCHMARK OFF CACHE BOOL "" FORCE) +set(INJA_INSTALL OFF CACHE BOOL "" FORCE) + +FetchContent_MakeAvailable(inja) + +FetchContent_Declare( + cmark + GIT_REPOSITORY https://github.com/commonmark/cmark.git + GIT_TAG 0.31.1 +) +FetchContent_MakeAvailable(cmark) + +file(GLOB AHSI_SOURCES CONFIGURE_DEPENDS src/*.cpp) + +add_executable(ahsi ${AHSI_SOURCES}) + +target_include_directories(ahsi PRIVATE + src + ${tomlplusplus_SOURCE_DIR}/include + ${json_SOURCE_DIR}/include + ${inja_SOURCE_DIR}/include +) + +target_link_libraries(ahsi PRIVATE cmark) + +set_target_properties(ahsi PROPERTIES + VERSION ${PROJECT_VERSION} + OUTPUT_NAME "ahsi" +) + diff --git a/README.md b/README.md new file mode 100644 index 0000000..506c8e6 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +ahsi +==== + +Simple static site generator written in C++. It uses markdown for source text +and toml for site configuration. + +Build +----- + +I use CMake for building the program. + +```sh +$ mkdir build && cd build +$ cmake .. +$ cmake --build . +``` + +Libraries +--------- + +I would thank to the folks. Ahsi never would have existed without those libaries. + +- Tomlplusplus by marzer +- Json by nlohman +- Inja by pantor +- Commonmark by cmark diff --git a/config.toml b/config.toml new file mode 100644 index 0000000..14ef4c6 --- /dev/null +++ b/config.toml @@ -0,0 +1,3 @@ +[main] +title = "radhitya.org" +url = "/" diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..bffbe5f --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,102 @@ +#include <iostream> +#include <string> +#include <string_view> +#include <toml++/toml.hpp> +#include <fstream> +#include <cassert> + +using namespace std::string_literals; +struct MainConfig { + std::string title; + std::string url; + std::string author; +}; + +struct FrontmatterConfig { + std::string title; + std::string date; + std::string categories; + std::string tags; + bool draft; +}; + +struct Config { + MainConfig main; + FrontmatterConfig frontmatter; +}; + +Config +parse_config(const std::string& filepath) +{ + toml::table tbl; + Config cfg; + + try { + tbl = toml::parse_file(filepath); + } catch (const toml::parse_error& err) { + std::cerr << "parsing failed: " << err << std::endl; + throw; + } + + if (auto* main = tbl["main"].as_table()) { + cfg.main.title = (*main)["title"].value_or("untitled's blog"); + cfg.main.url = (*main)["url"].value_or("localhost"); + cfg.main.author = (*main)["author"].value_or("linus"); + } + return cfg; +} + +Config +frontmatter(const std::string& filepath) +{ + Config cfg; + std::ifstream file(filepath); + std::string content((std::istreambuf_iterator<char>(file)), + std::istreambuf_iterator<char>()); + + const size_t first_fence = content.find("+++"); + const size_t second_fence = (first_fence == std::string::npos) + ? std::string::npos + : content.find("+++", first_fence + 3); + + /* TIL: npos == no position */ + if (first_fence != std::string::npos && second_fence != std::string::npos) { + std::string fm = content.substr(first_fence + 3, + second_fence - (first_fence+3)); + try { + toml::parse_result result = toml::parse(fm); + const toml::table& tbl = result; + cfg.frontmatter.title = tbl["title"].value_or(""s); + cfg.frontmatter.date = tbl["date"].value_or(""s); + cfg.frontmatter.categories = tbl["categories"].value_or(""s); + cfg.frontmatter.tags = tbl["tags"].value_or(""s); + cfg.frontmatter.draft = tbl["draft"].value_or(true); + } catch(const toml::parse_error& err) { + std::cerr << "parsing failed: " << err << std::endl; + throw; + } + } + return cfg; +} + +int main(int argc, char *argv[]) { + try { + Config my_config = parse_config("config.toml"); + + std::cout << "title name: " << my_config.main.title << std::endl; + std::cout << "url name: " << my_config.main.url << std::endl; + std::cout << "author: " << my_config.main.author << std::endl; + + Config front = frontmatter(argv[1]); + std::cout << "title page: " << front.frontmatter.title << std::endl; + std::cout << "title date: " << front.frontmatter.title << std::endl; + std::cout << "title categories: " << front.frontmatter.categories << std::endl; + std::cout << "title tags: " << front.frontmatter.tags << std::endl; + std::cout << "title draft: " << front.frontmatter.draft << std::endl; + + } catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + return 1; + } + return 0; +} |
