ferencd@0: /* ferencd@0: * This project is licensed under the MIT license. For more information see the ferencd@0: * LICENSE file. ferencd@0: */ ferencd@0: #pragma once ferencd@0: ferencd@0: // ----------------------------------------------------------------------------- ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: #include "maddy/parserconfig.h" ferencd@0: ferencd@0: // BlockParser ferencd@0: #include "maddy/checklistparser.h" ferencd@0: #include "maddy/codeblockparser.h" ferencd@0: #include "maddy/headlineparser.h" ferencd@0: #include "maddy/horizontallineparser.h" ferencd@0: #include "maddy/htmlparser.h" ferencd@0: #include "maddy/orderedlistparser.h" ferencd@0: #include "maddy/paragraphparser.h" ferencd@0: #include "maddy/quoteparser.h" ferencd@0: #include "maddy/tableparser.h" ferencd@0: #include "maddy/unorderedlistparser.h" ferencd@0: ferencd@0: // LineParser ferencd@0: #include "maddy/breaklineparser.h" ferencd@0: #include "maddy/emphasizedparser.h" ferencd@0: #include "maddy/imageparser.h" ferencd@0: #include "maddy/inlinecodeparser.h" ferencd@0: #include "maddy/italicparser.h" ferencd@0: #include "maddy/linkparser.h" ferencd@0: #include "maddy/strikethroughparser.h" ferencd@0: #include "maddy/strongparser.h" ferencd@0: ferencd@0: // ----------------------------------------------------------------------------- ferencd@0: ferencd@0: namespace maddy { ferencd@0: ferencd@0: // ----------------------------------------------------------------------------- ferencd@0: ferencd@0: /** ferencd@0: * Parser ferencd@0: * ferencd@0: * Transforms Markdown to HTML ferencd@0: * ferencd@0: * @class ferencd@0: */ ferencd@0: class Parser ferencd@0: { ferencd@0: public: ferencd@0: /** ferencd@0: * ctor ferencd@0: * ferencd@0: * Initializes all `LineParser` ferencd@0: * ferencd@0: * @method ferencd@0: */ ferencd@0: Parser(std::shared_ptr config = nullptr) ferencd@0: : config(config) ferencd@0: , breakLineParser(std::make_shared()) ferencd@0: , emphasizedParser(std::make_shared()) ferencd@0: , imageParser(std::make_shared()) ferencd@0: , inlineCodeParser(std::make_shared()) ferencd@0: , italicParser(std::make_shared()) ferencd@0: , linkParser(std::make_shared()) ferencd@0: , strikeThroughParser(std::make_shared()) ferencd@0: , strongParser(std::make_shared()) ferencd@0: {} ferencd@0: ferencd@0: /** ferencd@0: * Parse ferencd@0: * ferencd@0: * @method ferencd@0: * @param {const std::istream&} markdown ferencd@0: * @return {std::string} HTML ferencd@0: */ ferencd@0: std::string ferencd@0: Parse(std::istream& markdown) const ferencd@0: { ferencd@0: std::string result = ""; ferencd@0: std::shared_ptr currentBlockParser = nullptr; ferencd@0: ferencd@0: for (std::string line; std::getline(markdown, line);) ferencd@0: { ferencd@0: if (!currentBlockParser) ferencd@0: { ferencd@0: currentBlockParser = getBlockParserForLine(line); ferencd@0: } ferencd@0: ferencd@0: if (currentBlockParser) ferencd@0: { ferencd@0: currentBlockParser->AddLine(line); ferencd@0: ferencd@0: if (currentBlockParser->IsFinished()) ferencd@0: { ferencd@0: result += currentBlockParser->GetResult().str(); ferencd@0: currentBlockParser = nullptr; ferencd@0: } ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: // make sure, that all parsers are finished ferencd@0: if (currentBlockParser) ferencd@0: { ferencd@0: std::string emptyLine = ""; ferencd@0: currentBlockParser->AddLine(emptyLine); ferencd@0: if (currentBlockParser->IsFinished()) ferencd@0: { ferencd@0: result += currentBlockParser->GetResult().str(); ferencd@0: currentBlockParser = nullptr; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: return result; ferencd@0: } ferencd@0: ferencd@0: private: ferencd@0: std::shared_ptr config; ferencd@0: std::shared_ptr breakLineParser; ferencd@0: std::shared_ptr emphasizedParser; ferencd@0: std::shared_ptr imageParser; ferencd@0: std::shared_ptr inlineCodeParser; ferencd@0: std::shared_ptr italicParser; ferencd@0: std::shared_ptr linkParser; ferencd@0: std::shared_ptr strikeThroughParser; ferencd@0: std::shared_ptr strongParser; ferencd@0: ferencd@0: // block parser have to run before ferencd@0: void ferencd@0: runLineParser(std::string& line) const ferencd@0: { ferencd@0: // Attention! ImageParser has to be before LinkParser ferencd@0: this->imageParser->Parse(line); ferencd@0: this->linkParser->Parse(line); ferencd@0: ferencd@0: // Attention! StrongParser has to be before EmphasizedParser ferencd@0: this->strongParser->Parse(line); ferencd@0: ferencd@0: if (!this->config || this->config->isEmphasizedParserEnabled) ferencd@0: { ferencd@0: this->emphasizedParser->Parse(line); ferencd@0: } ferencd@0: ferencd@0: this->strikeThroughParser->Parse(line); ferencd@0: ferencd@0: this->inlineCodeParser->Parse(line); ferencd@0: ferencd@0: this->italicParser->Parse(line); ferencd@0: ferencd@0: this->breakLineParser->Parse(line); ferencd@0: } ferencd@0: ferencd@0: std::shared_ptr ferencd@0: getBlockParserForLine(const std::string& line) const ferencd@0: { ferencd@0: std::shared_ptr parser; ferencd@0: ferencd@0: if (maddy::CodeBlockParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = std::make_shared( ferencd@0: nullptr, ferencd@0: nullptr ferencd@0: ); ferencd@0: } ferencd@0: else if (maddy::HeadlineParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = std::make_shared( ferencd@0: nullptr, ferencd@0: nullptr ferencd@0: ); ferencd@0: } ferencd@0: else if (maddy::HorizontalLineParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = std::make_shared( ferencd@0: nullptr, ferencd@0: nullptr ferencd@0: ); ferencd@0: } ferencd@0: else if (maddy::QuoteParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = std::make_shared( ferencd@0: [this](std::string& line){ this->runLineParser(line); }, ferencd@0: [this](const std::string& line){ return this->getBlockParserForLine(line); } ferencd@0: ); ferencd@0: } ferencd@0: else if (maddy::TableParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = std::make_shared( ferencd@0: [this](std::string& line){ this->runLineParser(line); }, ferencd@0: nullptr ferencd@0: ); ferencd@0: } ferencd@0: else if (maddy::ChecklistParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createChecklistParser(); ferencd@0: } ferencd@0: else if (maddy::OrderedListParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createOrderedListParser(); ferencd@0: } ferencd@0: else if (maddy::UnorderedListParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createUnorderedListParser(); ferencd@0: } ferencd@0: else if ( ferencd@0: this->config && ferencd@0: !this->config->isHTMLWrappedInParagraph && ferencd@0: maddy::HtmlParser::IsStartingLine(line) ferencd@0: ) ferencd@0: { ferencd@0: parser = std::make_shared(nullptr, nullptr); ferencd@0: } ferencd@0: else if (maddy::ParagraphParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = std::make_shared( ferencd@0: [this](std::string& line){ this->runLineParser(line); }, ferencd@0: nullptr ferencd@0: ); ferencd@0: } ferencd@0: ferencd@0: return parser; ferencd@0: } ferencd@0: ferencd@0: std::shared_ptr ferencd@0: createChecklistParser() const ferencd@0: { ferencd@0: return std::make_shared( ferencd@0: [this](std::string& line){ this->runLineParser(line); }, ferencd@0: [this](const std::string& line) ferencd@0: { ferencd@0: std::shared_ptr parser; ferencd@0: ferencd@0: if (maddy::ChecklistParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createChecklistParser(); ferencd@0: } ferencd@0: ferencd@0: return parser; ferencd@0: } ferencd@0: ); ferencd@0: } ferencd@0: ferencd@0: std::shared_ptr ferencd@0: createOrderedListParser() const ferencd@0: { ferencd@0: return std::make_shared( ferencd@0: [this](std::string& line){ this->runLineParser(line); }, ferencd@0: [this](const std::string& line) ferencd@0: { ferencd@0: std::shared_ptr parser; ferencd@0: ferencd@0: if (maddy::OrderedListParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createOrderedListParser(); ferencd@0: } ferencd@0: else if (maddy::UnorderedListParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createUnorderedListParser(); ferencd@0: } ferencd@0: ferencd@0: return parser; ferencd@0: } ferencd@0: ); ferencd@0: } ferencd@0: ferencd@0: std::shared_ptr ferencd@0: createUnorderedListParser() const ferencd@0: { ferencd@0: return std::make_shared( ferencd@0: [this](std::string& line){ this->runLineParser(line); }, ferencd@0: [this](const std::string& line) ferencd@0: { ferencd@0: std::shared_ptr parser; ferencd@0: ferencd@0: if (maddy::OrderedListParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createOrderedListParser(); ferencd@0: } ferencd@0: else if (maddy::UnorderedListParser::IsStartingLine(line)) ferencd@0: { ferencd@0: parser = this->createUnorderedListParser(); ferencd@0: } ferencd@0: ferencd@0: return parser; ferencd@0: } ferencd@0: ); ferencd@0: } ferencd@0: }; // class Parser ferencd@0: ferencd@0: // ----------------------------------------------------------------------------- ferencd@0: ferencd@0: } // namespace maddy