aboutsummaryrefslogtreecommitdiffstats
path: root/include/markdown_translator.hpp
blob: 65eb545391f423de6c9aa8d825624fb1f2c70047 (plain) (blame)
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
#ifndef MARKDOWN_TRANSLATOR_H
#define MARKDOWN_TRANSLATOR_H

#include <string>
#include <vector>
#include <sstream>
#include <ctime>

class MarkdownTranslator {
public:
    // Constructor
    MarkdownTranslator();
    // Destructor
    ~MarkdownTranslator();
    // Main translation function - takes markdown content and returns HTML
    std::string translate(const std::string& markdownContent);
    std::string processLine(const std::string& line);

    void addExternalMenuItem(const std::string& name, const std::string& link){
        ExternalMenuItem menuItem{name, link};
        externalMenuLinks.push_back(menuItem);
    }
    enum Theme {
        carbon
    };

    struct ExternalMenuItem{
        std::string name;
        std::string link;
    };

    std::vector<ExternalMenuItem> externalMenuLinks;


private:
    // Regex for various tags
    const std::string headerRegexStr{"^(#{1,6})\\s+(.*)$"};
    const std::string boldRegexStr{"\\*\\*([^\\*]+)\\*\\*|__([^_]+)__"};
    const std::string italicRegexStr{"\\*([^\\*]+)\\*|_([^_]+)_"};
    const std::string linkRegexStr{"\\[([^\\]]+)\\]\\(([^\\)]+)\\)"};
    const std::string imageRegexStr{"!\\[(.*?)\\]\\(([^\\s\"]+)(\\s+\"(.*?)\")?\\)"};
    // Helper functions for different markdown elements
    void processMetadata(const std::vector<std::string>& lines);
    std::string processHeaders(const std::string& line);
    std::string processBold(const std::string& text);
    std::string processItalic(const std::string& text);
    std::string processLinks(const std::string& text);
    std::string processParagraph(const std::string& text);
    std::string processSingleFigure(const std::string& text);
    std::string processFigureBlock(const std::vector<std::string>& lines);
    // Navigation and table of contents
    void prescanHeaders(std::stringstream& markdownStream);
    void generateSideBar(std::stringstream& output);
    std::string createAnchorId(const std::string& text);
    // Utility functions

    std::string getCurrentDateTime() {
        std::time_t now = std::time(nullptr);
        std::tm* localTime = std::localtime(&now);

        char buffer[80];
        std::strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", localTime);

        return std::string(buffer);
    }

    // HTML builders
    std::string buildHTMLHeader(const std::string& title){
        return R"(<!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>)" + title + R"(</title>
            <link rel="stylesheet" href=")" + cssPath + R"(">
        </head>
        <body>
        )";
    }

    std::string buildHTMLFooter(){
                return R"( <div class="article-meta">
                        <p>Last updated: )" + getCurrentDateTime() + R"(</p>
                    </div>
                </div>
            </div>
        </body>
        </html>
        )";
    }

    void setTheme(const Theme& theme){
        switch(theme){
            case Theme::carbon:
                cssPath = "styles/carbon.css";
                break;
            default:
                cssPath = "styles/carbon.css";
        }
    }

    // Member variables
    std::string title;
    std::string cssPath{"styles/carbon.css"};
    std::vector<std::string> headers; // h1-6

};

#endif // MARKDOWN_TRANSLATOR_H
send patches to the email below
yukais@pinapelz.com
include the subject [PATCH repo_name]
pinapelz.com
homepage