diff options
| -rw-r--r-- | include/markdown_translator.hpp | 14 | ||||
| -rw-r--r-- | src/markdown_translator.cpp | 64 | ||||
| -rw-r--r-- | styles/carbon.css | 35 |
3 files changed, 70 insertions, 43 deletions
diff --git a/include/markdown_translator.hpp b/include/markdown_translator.hpp index f62f7a0..4a62cbc 100644 --- a/include/markdown_translator.hpp +++ b/include/markdown_translator.hpp @@ -19,7 +19,7 @@ public: externalMenuLinks.push_back(menuItem); } enum Theme { - carbon + CARBON }; struct ExternalMenuItem{ @@ -46,6 +46,7 @@ private: std::string processParagraph(const std::string& text); std::string processSingleFigure(const std::string& text); std::string processFigureBlock(const std::vector<std::string>& lines); + std::string processCodeBlock(const std::string& language, const std::vector<std::string>& lines); // Navigation and table of contents void prescanHeaders(std::stringstream& markdownStream); void generateSideBar(std::stringstream& output); @@ -71,6 +72,7 @@ private: <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>)" + title + R"(</title> <link rel="stylesheet" href=")" + cssPath + R"("> + <link href="https://unpkg.com/prism-themes@1.6.0/themes/prism-atom-dark.css" rel="stylesheet"> </head> <body> )"; @@ -82,6 +84,8 @@ private: </div> </div> </div> + <script src="https://unpkg.com/prismjs@1.30.0/prism.js"></script> + <script src="https://unpkg.com/prismjs@1.30.0/plugins/autoloader/prism-autoloader.min.js"></script> </body> </html> )"; @@ -89,7 +93,7 @@ private: void setTheme(const Theme& theme){ switch(theme){ - case Theme::carbon: + case Theme::CARBON: cssPath = "styles/carbon.css"; break; default: @@ -102,6 +106,12 @@ private: std::string cssPath{"styles/carbon.css"}; std::vector<std::string> headers; // h1-6 + enum ParseState { + REGULAR, + IN_FIGURE, + IN_CODEBLOCK, + }; + }; #endif // MARKDOWN_TRANSLATOR_H diff --git a/src/markdown_translator.cpp b/src/markdown_translator.cpp index 1eb2950..ee4c6ff 100644 --- a/src/markdown_translator.cpp +++ b/src/markdown_translator.cpp @@ -108,29 +108,52 @@ std::string MarkdownTranslator::translate(const std::string& markdownContent) { // Process each line of markdown // State of current parse - bool inFigureBlock{false}; + MarkdownTranslator::ParseState parseState = MarkdownTranslator::ParseState::REGULAR; std::vector<std::string> figureLines; - while (std::getline(markdownStream, line)) { + std::vector<std::string> codeblockLines; + std::string language; + + while (std::getline(markdownStream, line)) { // Start of figure block if(line.find(":::figure") == 0){ - inFigureBlock = true; + parseState = MarkdownTranslator::ParseState::IN_FIGURE; figureLines.clear(); continue; } - - if(inFigureBlock && line == ":::"){ - inFigureBlock = false; + if(parseState == MarkdownTranslator::ParseState::IN_FIGURE && line == ":::"){ // End of figure block + parseState = MarkdownTranslator::ParseState::REGULAR; htmlOutput << " " << processFigureBlock(figureLines) << "\n"; continue; } - else if(inFigureBlock){ + else if(parseState == MarkdownTranslator::ParseState::IN_FIGURE){ figureLines.push_back(line); continue; } + if(line.find("```") == 0 && parseState != MarkdownTranslator::ParseState::IN_CODEBLOCK){ + parseState = MarkdownTranslator::ParseState::IN_CODEBLOCK; + codeblockLines.clear(); + if(line.length() > 3) { + language = line.substr(3); + } + std::cout << language << std::endl; + continue; + } + else if(parseState == MarkdownTranslator::ParseState::IN_CODEBLOCK && line == "```"){ // End of figure block + parseState = MarkdownTranslator::ParseState::REGULAR; + htmlOutput << " " << processCodeBlock(language, codeblockLines) << "\n"; + continue; + } + else if(parseState == MarkdownTranslator::ParseState::IN_CODEBLOCK){ + codeblockLines.push_back(line); + continue; + } + htmlOutput << " " << processLine(line); } + htmlOutput << buildHTMLFooter(); + return htmlOutput.str(); } @@ -289,3 +312,30 @@ std::string MarkdownTranslator::processFigureBlock(const std::vector<std::string html << "</figure>"; return html.str(); } + +std::string htmlEscape(const std::string& text) { + std::string escaped; + escaped.reserve(text.size()); + for (char c : text) { + switch (c) { + case '&': escaped += "&"; break; + case '<': escaped += "<"; break; + case '>': escaped += ">"; break; + case '"': escaped += """; break; + case '\'': escaped += "'"; break; + default: escaped += c; break; + } + } + return escaped; +} +std::string MarkdownTranslator::processCodeBlock( + const std::string& language, + const std::vector<std::string>& lines +) { + std::stringstream html; + html << "<pre><code class=\"language-"<< language <<"\">"; + for (const auto& line : lines) + html << htmlEscape(line) << '\n'; + html << "</code></pre>"; + return html.str(); +} diff --git a/styles/carbon.css b/styles/carbon.css index 247a2b2..2cc3575 100644 --- a/styles/carbon.css +++ b/styles/carbon.css @@ -13,7 +13,6 @@ --link-hover: #a5d0f0; --header-gradient-start: #2a2a2a; --header-gradient-end: #1a1a1a; - --code-bg: #0d0d0d; --nav-bg: #1f1f1f; --nav-hover: #333333; } @@ -281,38 +280,7 @@ ol li::marker { font-weight: bold; } -/* Code blocks with FFXIV terminal style */ -pre { - background-color: var(--code-bg); - border: 1px solid var(--border-color); - border-left: 4px solid var(--accent-blue); - padding: 15px; - margin: 1.5em 0; - overflow-x: auto; - font-family: "Consolas", "Monaco", monospace; - font-size: 0.9em; - line-height: 1.5; - box-shadow: inset 0 2px 10px rgba(0, 0, 0, 0.5); -} - -code { - background-color: var(--code-bg); - color: var(--accent-blue); - padding: 3px 6px; - border-radius: 3px; - font-family: "Consolas", "Monaco", monospace; - font-size: 0.9em; - border: 1px solid var(--border-color); -} -pre code { - background-color: transparent; - color: var(--text-primary); - padding: 0; - border: none; -} - -/* Blockquotes with FFXIV quest text styling */ blockquote { border-left: 4px solid var(--accent-gold); background: linear-gradient(90deg, rgba(201, 170, 113, 0.1), transparent); @@ -372,7 +340,6 @@ tr:hover td { background-color: rgba(201, 170, 113, 0.05); } -/* Horizontal rules with FFXIV ornamental style */ hr { border: none; height: 2px; @@ -636,7 +603,7 @@ img { font-size: 1.3em; } } - +Blockquote /* Animation for page load */ @keyframes fadeIn { from { |
