summaryrefslogtreecommitdiff
path: root/src/main.cpp
blob: 0902b19d71f93cb3a58d6970034261bf0d8a6800 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include <string>
#include <string_view>
#include <toml++/toml.hpp>
#include <fstream>
#include <cassert>
#include <cmark.h>

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;
  std::string body;
};

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;
    }
    cfg.frontmatter.body = content.substr(second_fence + 3);
  }
  return cfg;
}

std::string
markdown_processing(const std::string& md) {
  char *raw = cmark_markdown_to_html(md.c_str(), md.size(),0);
  std::string html(raw);
  free(raw);
  return html;
}

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.date << 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;
    std::cout << "title body: " << markdown_processing(front.frontmatter.body) << std::endl;

  } catch (const std::exception& e) {
    std::cerr << e.what() << std::endl;
    return 1;
  }
  return 0;
}