summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt62
-rw-r--r--README.md26
-rw-r--r--config.toml3
-rw-r--r--src/main.cpp102
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;
+}