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