|
ferencd@0
|
1 /*
|
|
ferencd@0
|
2 * This project is licensed under the MIT license. For more information see the
|
|
ferencd@0
|
3 * LICENSE file.
|
|
ferencd@0
|
4 */
|
|
ferencd@0
|
5 #pragma once
|
|
ferencd@0
|
6
|
|
ferencd@0
|
7 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
8
|
|
ferencd@0
|
9 #include <memory>
|
|
ferencd@0
|
10 #include <functional>
|
|
ferencd@0
|
11 #include <string>
|
|
ferencd@0
|
12
|
|
ferencd@0
|
13 #include "maddy/parserconfig.h"
|
|
ferencd@0
|
14
|
|
ferencd@0
|
15 // BlockParser
|
|
ferencd@0
|
16 #include "maddy/checklistparser.h"
|
|
ferencd@0
|
17 #include "maddy/codeblockparser.h"
|
|
ferencd@0
|
18 #include "maddy/headlineparser.h"
|
|
ferencd@0
|
19 #include "maddy/horizontallineparser.h"
|
|
ferencd@0
|
20 #include "maddy/htmlparser.h"
|
|
ferencd@0
|
21 #include "maddy/orderedlistparser.h"
|
|
ferencd@0
|
22 #include "maddy/paragraphparser.h"
|
|
ferencd@0
|
23 #include "maddy/quoteparser.h"
|
|
ferencd@0
|
24 #include "maddy/tableparser.h"
|
|
ferencd@0
|
25 #include "maddy/unorderedlistparser.h"
|
|
ferencd@0
|
26
|
|
ferencd@0
|
27 // LineParser
|
|
ferencd@0
|
28 #include "maddy/breaklineparser.h"
|
|
ferencd@0
|
29 #include "maddy/emphasizedparser.h"
|
|
ferencd@0
|
30 #include "maddy/imageparser.h"
|
|
ferencd@0
|
31 #include "maddy/inlinecodeparser.h"
|
|
ferencd@0
|
32 #include "maddy/italicparser.h"
|
|
ferencd@0
|
33 #include "maddy/linkparser.h"
|
|
ferencd@0
|
34 #include "maddy/strikethroughparser.h"
|
|
ferencd@0
|
35 #include "maddy/strongparser.h"
|
|
ferencd@0
|
36
|
|
ferencd@0
|
37 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
38
|
|
ferencd@0
|
39 namespace maddy {
|
|
ferencd@0
|
40
|
|
ferencd@0
|
41 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
42
|
|
ferencd@0
|
43 /**
|
|
ferencd@0
|
44 * Parser
|
|
ferencd@0
|
45 *
|
|
ferencd@0
|
46 * Transforms Markdown to HTML
|
|
ferencd@0
|
47 *
|
|
ferencd@0
|
48 * @class
|
|
ferencd@0
|
49 */
|
|
ferencd@0
|
50 class Parser
|
|
ferencd@0
|
51 {
|
|
ferencd@0
|
52 public:
|
|
ferencd@0
|
53 /**
|
|
ferencd@0
|
54 * ctor
|
|
ferencd@0
|
55 *
|
|
ferencd@0
|
56 * Initializes all `LineParser`
|
|
ferencd@0
|
57 *
|
|
ferencd@0
|
58 * @method
|
|
ferencd@0
|
59 */
|
|
ferencd@0
|
60 Parser(std::shared_ptr<ParserConfig> config = nullptr)
|
|
ferencd@0
|
61 : config(config)
|
|
ferencd@0
|
62 , breakLineParser(std::make_shared<BreakLineParser>())
|
|
ferencd@0
|
63 , emphasizedParser(std::make_shared<EmphasizedParser>())
|
|
ferencd@0
|
64 , imageParser(std::make_shared<ImageParser>())
|
|
ferencd@0
|
65 , inlineCodeParser(std::make_shared<InlineCodeParser>())
|
|
ferencd@0
|
66 , italicParser(std::make_shared<ItalicParser>())
|
|
ferencd@0
|
67 , linkParser(std::make_shared<LinkParser>())
|
|
ferencd@0
|
68 , strikeThroughParser(std::make_shared<StrikeThroughParser>())
|
|
ferencd@0
|
69 , strongParser(std::make_shared<StrongParser>())
|
|
ferencd@0
|
70 {}
|
|
ferencd@0
|
71
|
|
ferencd@0
|
72 /**
|
|
ferencd@0
|
73 * Parse
|
|
ferencd@0
|
74 *
|
|
ferencd@0
|
75 * @method
|
|
ferencd@0
|
76 * @param {const std::istream&} markdown
|
|
ferencd@0
|
77 * @return {std::string} HTML
|
|
ferencd@0
|
78 */
|
|
ferencd@0
|
79 std::string
|
|
ferencd@0
|
80 Parse(std::istream& markdown) const
|
|
ferencd@0
|
81 {
|
|
ferencd@0
|
82 std::string result = "";
|
|
ferencd@0
|
83 std::shared_ptr<BlockParser> currentBlockParser = nullptr;
|
|
ferencd@0
|
84
|
|
ferencd@0
|
85 for (std::string line; std::getline(markdown, line);)
|
|
ferencd@0
|
86 {
|
|
ferencd@0
|
87 if (!currentBlockParser)
|
|
ferencd@0
|
88 {
|
|
ferencd@0
|
89 currentBlockParser = getBlockParserForLine(line);
|
|
ferencd@0
|
90 }
|
|
ferencd@0
|
91
|
|
ferencd@0
|
92 if (currentBlockParser)
|
|
ferencd@0
|
93 {
|
|
ferencd@0
|
94 currentBlockParser->AddLine(line);
|
|
ferencd@0
|
95
|
|
ferencd@0
|
96 if (currentBlockParser->IsFinished())
|
|
ferencd@0
|
97 {
|
|
ferencd@0
|
98 result += currentBlockParser->GetResult().str();
|
|
ferencd@0
|
99 currentBlockParser = nullptr;
|
|
ferencd@0
|
100 }
|
|
ferencd@0
|
101 }
|
|
ferencd@0
|
102 }
|
|
ferencd@0
|
103
|
|
ferencd@0
|
104 // make sure, that all parsers are finished
|
|
ferencd@0
|
105 if (currentBlockParser)
|
|
ferencd@0
|
106 {
|
|
ferencd@0
|
107 std::string emptyLine = "";
|
|
ferencd@0
|
108 currentBlockParser->AddLine(emptyLine);
|
|
ferencd@0
|
109 if (currentBlockParser->IsFinished())
|
|
ferencd@0
|
110 {
|
|
ferencd@0
|
111 result += currentBlockParser->GetResult().str();
|
|
ferencd@0
|
112 currentBlockParser = nullptr;
|
|
ferencd@0
|
113 }
|
|
ferencd@0
|
114 }
|
|
ferencd@0
|
115
|
|
ferencd@0
|
116 return result;
|
|
ferencd@0
|
117 }
|
|
ferencd@0
|
118
|
|
ferencd@0
|
119 private:
|
|
ferencd@0
|
120 std::shared_ptr<ParserConfig> config;
|
|
ferencd@0
|
121 std::shared_ptr<BreakLineParser> breakLineParser;
|
|
ferencd@0
|
122 std::shared_ptr<EmphasizedParser> emphasizedParser;
|
|
ferencd@0
|
123 std::shared_ptr<ImageParser> imageParser;
|
|
ferencd@0
|
124 std::shared_ptr<InlineCodeParser> inlineCodeParser;
|
|
ferencd@0
|
125 std::shared_ptr<ItalicParser> italicParser;
|
|
ferencd@0
|
126 std::shared_ptr<LinkParser> linkParser;
|
|
ferencd@0
|
127 std::shared_ptr<StrikeThroughParser> strikeThroughParser;
|
|
ferencd@0
|
128 std::shared_ptr<StrongParser> strongParser;
|
|
ferencd@0
|
129
|
|
ferencd@0
|
130 // block parser have to run before
|
|
ferencd@0
|
131 void
|
|
ferencd@0
|
132 runLineParser(std::string& line) const
|
|
ferencd@0
|
133 {
|
|
ferencd@0
|
134 // Attention! ImageParser has to be before LinkParser
|
|
ferencd@0
|
135 this->imageParser->Parse(line);
|
|
ferencd@0
|
136 this->linkParser->Parse(line);
|
|
ferencd@0
|
137
|
|
ferencd@0
|
138 // Attention! StrongParser has to be before EmphasizedParser
|
|
ferencd@0
|
139 this->strongParser->Parse(line);
|
|
ferencd@0
|
140
|
|
ferencd@0
|
141 if (!this->config || this->config->isEmphasizedParserEnabled)
|
|
ferencd@0
|
142 {
|
|
ferencd@0
|
143 this->emphasizedParser->Parse(line);
|
|
ferencd@0
|
144 }
|
|
ferencd@0
|
145
|
|
ferencd@0
|
146 this->strikeThroughParser->Parse(line);
|
|
ferencd@0
|
147
|
|
ferencd@0
|
148 this->inlineCodeParser->Parse(line);
|
|
ferencd@0
|
149
|
|
ferencd@0
|
150 this->italicParser->Parse(line);
|
|
ferencd@0
|
151
|
|
ferencd@0
|
152 this->breakLineParser->Parse(line);
|
|
ferencd@0
|
153 }
|
|
ferencd@0
|
154
|
|
ferencd@0
|
155 std::shared_ptr<BlockParser>
|
|
ferencd@0
|
156 getBlockParserForLine(const std::string& line) const
|
|
ferencd@0
|
157 {
|
|
ferencd@0
|
158 std::shared_ptr<BlockParser> parser;
|
|
ferencd@0
|
159
|
|
ferencd@0
|
160 if (maddy::CodeBlockParser::IsStartingLine(line))
|
|
ferencd@0
|
161 {
|
|
ferencd@0
|
162 parser = std::make_shared<maddy::CodeBlockParser>(
|
|
ferencd@0
|
163 nullptr,
|
|
ferencd@0
|
164 nullptr
|
|
ferencd@0
|
165 );
|
|
ferencd@0
|
166 }
|
|
ferencd@0
|
167 else if (maddy::HeadlineParser::IsStartingLine(line))
|
|
ferencd@0
|
168 {
|
|
ferencd@0
|
169 parser = std::make_shared<maddy::HeadlineParser>(
|
|
ferencd@0
|
170 nullptr,
|
|
ferencd@0
|
171 nullptr
|
|
ferencd@0
|
172 );
|
|
ferencd@0
|
173 }
|
|
ferencd@0
|
174 else if (maddy::HorizontalLineParser::IsStartingLine(line))
|
|
ferencd@0
|
175 {
|
|
ferencd@0
|
176 parser = std::make_shared<maddy::HorizontalLineParser>(
|
|
ferencd@0
|
177 nullptr,
|
|
ferencd@0
|
178 nullptr
|
|
ferencd@0
|
179 );
|
|
ferencd@0
|
180 }
|
|
ferencd@0
|
181 else if (maddy::QuoteParser::IsStartingLine(line))
|
|
ferencd@0
|
182 {
|
|
ferencd@0
|
183 parser = std::make_shared<maddy::QuoteParser>(
|
|
ferencd@0
|
184 [this](std::string& line){ this->runLineParser(line); },
|
|
ferencd@0
|
185 [this](const std::string& line){ return this->getBlockParserForLine(line); }
|
|
ferencd@0
|
186 );
|
|
ferencd@0
|
187 }
|
|
ferencd@0
|
188 else if (maddy::TableParser::IsStartingLine(line))
|
|
ferencd@0
|
189 {
|
|
ferencd@0
|
190 parser = std::make_shared<maddy::TableParser>(
|
|
ferencd@0
|
191 [this](std::string& line){ this->runLineParser(line); },
|
|
ferencd@0
|
192 nullptr
|
|
ferencd@0
|
193 );
|
|
ferencd@0
|
194 }
|
|
ferencd@0
|
195 else if (maddy::ChecklistParser::IsStartingLine(line))
|
|
ferencd@0
|
196 {
|
|
ferencd@0
|
197 parser = this->createChecklistParser();
|
|
ferencd@0
|
198 }
|
|
ferencd@0
|
199 else if (maddy::OrderedListParser::IsStartingLine(line))
|
|
ferencd@0
|
200 {
|
|
ferencd@0
|
201 parser = this->createOrderedListParser();
|
|
ferencd@0
|
202 }
|
|
ferencd@0
|
203 else if (maddy::UnorderedListParser::IsStartingLine(line))
|
|
ferencd@0
|
204 {
|
|
ferencd@0
|
205 parser = this->createUnorderedListParser();
|
|
ferencd@0
|
206 }
|
|
ferencd@0
|
207 else if (
|
|
ferencd@0
|
208 this->config &&
|
|
ferencd@0
|
209 !this->config->isHTMLWrappedInParagraph &&
|
|
ferencd@0
|
210 maddy::HtmlParser::IsStartingLine(line)
|
|
ferencd@0
|
211 )
|
|
ferencd@0
|
212 {
|
|
ferencd@0
|
213 parser = std::make_shared<maddy::HtmlParser>(nullptr, nullptr);
|
|
ferencd@0
|
214 }
|
|
ferencd@0
|
215 else if (maddy::ParagraphParser::IsStartingLine(line))
|
|
ferencd@0
|
216 {
|
|
ferencd@0
|
217 parser = std::make_shared<maddy::ParagraphParser>(
|
|
ferencd@0
|
218 [this](std::string& line){ this->runLineParser(line); },
|
|
ferencd@0
|
219 nullptr
|
|
ferencd@0
|
220 );
|
|
ferencd@0
|
221 }
|
|
ferencd@0
|
222
|
|
ferencd@0
|
223 return parser;
|
|
ferencd@0
|
224 }
|
|
ferencd@0
|
225
|
|
ferencd@0
|
226 std::shared_ptr<BlockParser>
|
|
ferencd@0
|
227 createChecklistParser() const
|
|
ferencd@0
|
228 {
|
|
ferencd@0
|
229 return std::make_shared<maddy::ChecklistParser>(
|
|
ferencd@0
|
230 [this](std::string& line){ this->runLineParser(line); },
|
|
ferencd@0
|
231 [this](const std::string& line)
|
|
ferencd@0
|
232 {
|
|
ferencd@0
|
233 std::shared_ptr<BlockParser> parser;
|
|
ferencd@0
|
234
|
|
ferencd@0
|
235 if (maddy::ChecklistParser::IsStartingLine(line))
|
|
ferencd@0
|
236 {
|
|
ferencd@0
|
237 parser = this->createChecklistParser();
|
|
ferencd@0
|
238 }
|
|
ferencd@0
|
239
|
|
ferencd@0
|
240 return parser;
|
|
ferencd@0
|
241 }
|
|
ferencd@0
|
242 );
|
|
ferencd@0
|
243 }
|
|
ferencd@0
|
244
|
|
ferencd@0
|
245 std::shared_ptr<BlockParser>
|
|
ferencd@0
|
246 createOrderedListParser() const
|
|
ferencd@0
|
247 {
|
|
ferencd@0
|
248 return std::make_shared<maddy::OrderedListParser>(
|
|
ferencd@0
|
249 [this](std::string& line){ this->runLineParser(line); },
|
|
ferencd@0
|
250 [this](const std::string& line)
|
|
ferencd@0
|
251 {
|
|
ferencd@0
|
252 std::shared_ptr<BlockParser> parser;
|
|
ferencd@0
|
253
|
|
ferencd@0
|
254 if (maddy::OrderedListParser::IsStartingLine(line))
|
|
ferencd@0
|
255 {
|
|
ferencd@0
|
256 parser = this->createOrderedListParser();
|
|
ferencd@0
|
257 }
|
|
ferencd@0
|
258 else if (maddy::UnorderedListParser::IsStartingLine(line))
|
|
ferencd@0
|
259 {
|
|
ferencd@0
|
260 parser = this->createUnorderedListParser();
|
|
ferencd@0
|
261 }
|
|
ferencd@0
|
262
|
|
ferencd@0
|
263 return parser;
|
|
ferencd@0
|
264 }
|
|
ferencd@0
|
265 );
|
|
ferencd@0
|
266 }
|
|
ferencd@0
|
267
|
|
ferencd@0
|
268 std::shared_ptr<BlockParser>
|
|
ferencd@0
|
269 createUnorderedListParser() const
|
|
ferencd@0
|
270 {
|
|
ferencd@0
|
271 return std::make_shared<maddy::UnorderedListParser>(
|
|
ferencd@0
|
272 [this](std::string& line){ this->runLineParser(line); },
|
|
ferencd@0
|
273 [this](const std::string& line)
|
|
ferencd@0
|
274 {
|
|
ferencd@0
|
275 std::shared_ptr<BlockParser> parser;
|
|
ferencd@0
|
276
|
|
ferencd@0
|
277 if (maddy::OrderedListParser::IsStartingLine(line))
|
|
ferencd@0
|
278 {
|
|
ferencd@0
|
279 parser = this->createOrderedListParser();
|
|
ferencd@0
|
280 }
|
|
ferencd@0
|
281 else if (maddy::UnorderedListParser::IsStartingLine(line))
|
|
ferencd@0
|
282 {
|
|
ferencd@0
|
283 parser = this->createUnorderedListParser();
|
|
ferencd@0
|
284 }
|
|
ferencd@0
|
285
|
|
ferencd@0
|
286 return parser;
|
|
ferencd@0
|
287 }
|
|
ferencd@0
|
288 );
|
|
ferencd@0
|
289 }
|
|
ferencd@0
|
290 }; // class Parser
|
|
ferencd@0
|
291
|
|
ferencd@0
|
292 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
293
|
|
ferencd@0
|
294 } // namespace maddy
|