|
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 <functional>
|
|
ferencd@0
|
10 #include <regex>
|
|
ferencd@0
|
11 #include <string>
|
|
ferencd@0
|
12
|
|
ferencd@0
|
13 #include "maddy/blockparser.h"
|
|
ferencd@0
|
14
|
|
ferencd@0
|
15 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
16
|
|
ferencd@0
|
17 namespace maddy {
|
|
ferencd@0
|
18
|
|
ferencd@0
|
19 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
20
|
|
ferencd@0
|
21 /**
|
|
ferencd@0
|
22 * QuoteParser
|
|
ferencd@0
|
23 *
|
|
ferencd@0
|
24 * @class
|
|
ferencd@0
|
25 */
|
|
ferencd@0
|
26 class QuoteParser : public BlockParser
|
|
ferencd@0
|
27 {
|
|
ferencd@0
|
28 public:
|
|
ferencd@0
|
29 /**
|
|
ferencd@0
|
30 * ctor
|
|
ferencd@0
|
31 *
|
|
ferencd@0
|
32 * @method
|
|
ferencd@0
|
33 * @param {std::function<void(std::string&)>} parseLineCallback
|
|
ferencd@0
|
34 * @param {std::function<std::shared_ptr<BlockParser>(const std::string& line)>} getBlockParserForLineCallback
|
|
ferencd@0
|
35 */
|
|
ferencd@0
|
36 QuoteParser(
|
|
ferencd@0
|
37 std::function<void(std::string&)> parseLineCallback,
|
|
ferencd@0
|
38 std::function<std::shared_ptr<BlockParser>(const std::string& line)> getBlockParserForLineCallback
|
|
ferencd@0
|
39 )
|
|
ferencd@0
|
40 : BlockParser(parseLineCallback, getBlockParserForLineCallback)
|
|
ferencd@0
|
41 , isStarted(false)
|
|
ferencd@0
|
42 , isFinished(false)
|
|
ferencd@0
|
43 {}
|
|
ferencd@0
|
44
|
|
ferencd@0
|
45 /**
|
|
ferencd@0
|
46 * IsStartingLine
|
|
ferencd@0
|
47 *
|
|
ferencd@0
|
48 * A quote starts with `> `.
|
|
ferencd@0
|
49 *
|
|
ferencd@0
|
50 * @method
|
|
ferencd@0
|
51 * @param {const std::string&} line
|
|
ferencd@0
|
52 * @return {bool}
|
|
ferencd@0
|
53 */
|
|
ferencd@0
|
54 static bool
|
|
ferencd@0
|
55 IsStartingLine(const std::string& line)
|
|
ferencd@0
|
56 {
|
|
ferencd@0
|
57 static std::regex re("^\\>.*");
|
|
ferencd@0
|
58 return std::regex_match(line, re);
|
|
ferencd@0
|
59 }
|
|
ferencd@0
|
60
|
|
ferencd@0
|
61 /**
|
|
ferencd@0
|
62 * AddLine
|
|
ferencd@0
|
63 *
|
|
ferencd@0
|
64 * Adding a line which has to be parsed.
|
|
ferencd@0
|
65 *
|
|
ferencd@0
|
66 * @method
|
|
ferencd@0
|
67 * @param {std::string&} line
|
|
ferencd@0
|
68 * @return {void}
|
|
ferencd@0
|
69 */
|
|
ferencd@0
|
70 void
|
|
ferencd@0
|
71 AddLine(std::string& line) override
|
|
ferencd@0
|
72 {
|
|
ferencd@0
|
73 if (!this->isStarted)
|
|
ferencd@0
|
74 {
|
|
ferencd@0
|
75 this->result << "<blockquote>";
|
|
ferencd@0
|
76 this->isStarted = true;
|
|
ferencd@0
|
77 }
|
|
ferencd@0
|
78
|
|
ferencd@0
|
79 bool finish = false;
|
|
ferencd@0
|
80 if (line.empty())
|
|
ferencd@0
|
81 {
|
|
ferencd@0
|
82 finish = true;
|
|
ferencd@0
|
83 }
|
|
ferencd@0
|
84
|
|
ferencd@0
|
85 this->parseBlock(line);
|
|
ferencd@0
|
86
|
|
ferencd@0
|
87 if (this->isInlineBlockAllowed() && !this->childParser)
|
|
ferencd@0
|
88 {
|
|
ferencd@0
|
89 this->childParser = this->getBlockParserForLine(line);
|
|
ferencd@0
|
90 }
|
|
ferencd@0
|
91
|
|
ferencd@0
|
92 if (this->childParser)
|
|
ferencd@0
|
93 {
|
|
ferencd@0
|
94 this->childParser->AddLine(line);
|
|
ferencd@0
|
95
|
|
ferencd@0
|
96 if (this->childParser->IsFinished())
|
|
ferencd@0
|
97 {
|
|
ferencd@0
|
98 this->result << this->childParser->GetResult().str();
|
|
ferencd@0
|
99 this->childParser = nullptr;
|
|
ferencd@0
|
100 }
|
|
ferencd@0
|
101
|
|
ferencd@0
|
102 return;
|
|
ferencd@0
|
103 }
|
|
ferencd@0
|
104
|
|
ferencd@0
|
105 if (this->isLineParserAllowed())
|
|
ferencd@0
|
106 {
|
|
ferencd@0
|
107 this->parseLine(line);
|
|
ferencd@0
|
108 }
|
|
ferencd@0
|
109
|
|
ferencd@0
|
110 if (finish)
|
|
ferencd@0
|
111 {
|
|
ferencd@0
|
112 this->result << "</blockquote>";
|
|
ferencd@0
|
113 this->isFinished = true;
|
|
ferencd@0
|
114 }
|
|
ferencd@0
|
115
|
|
ferencd@0
|
116 this->result << line;
|
|
ferencd@0
|
117 }
|
|
ferencd@0
|
118
|
|
ferencd@0
|
119 /**
|
|
ferencd@0
|
120 * IsFinished
|
|
ferencd@0
|
121 *
|
|
ferencd@0
|
122 * @method
|
|
ferencd@0
|
123 * @return {bool}
|
|
ferencd@0
|
124 */
|
|
ferencd@0
|
125 bool
|
|
ferencd@0
|
126 IsFinished() const override
|
|
ferencd@0
|
127 {
|
|
ferencd@0
|
128 return this->isFinished;
|
|
ferencd@0
|
129 }
|
|
ferencd@0
|
130
|
|
ferencd@0
|
131 protected:
|
|
ferencd@0
|
132 bool
|
|
ferencd@0
|
133 isInlineBlockAllowed() const override
|
|
ferencd@0
|
134 {
|
|
ferencd@0
|
135 return true;
|
|
ferencd@0
|
136 }
|
|
ferencd@0
|
137
|
|
ferencd@0
|
138 bool
|
|
ferencd@0
|
139 isLineParserAllowed() const override
|
|
ferencd@0
|
140 {
|
|
ferencd@0
|
141 return true;
|
|
ferencd@0
|
142 }
|
|
ferencd@0
|
143
|
|
ferencd@0
|
144 void
|
|
ferencd@0
|
145 parseBlock(std::string& line) override
|
|
ferencd@0
|
146 {
|
|
ferencd@0
|
147 static std::regex lineRegexWithSpace("^\\> ");
|
|
ferencd@0
|
148 line = std::regex_replace(line, lineRegexWithSpace, "");
|
|
ferencd@0
|
149 static std::regex lineRegexWithoutSpace("^\\>");
|
|
ferencd@0
|
150 line = std::regex_replace(line, lineRegexWithoutSpace, "");
|
|
ferencd@0
|
151
|
|
ferencd@0
|
152 if (!line.empty())
|
|
ferencd@0
|
153 {
|
|
ferencd@0
|
154 line += " ";
|
|
ferencd@0
|
155 }
|
|
ferencd@0
|
156 }
|
|
ferencd@0
|
157
|
|
ferencd@0
|
158 private:
|
|
ferencd@0
|
159 bool isStarted;
|
|
ferencd@0
|
160 bool isFinished;
|
|
ferencd@0
|
161 }; // class QuoteParser
|
|
ferencd@0
|
162
|
|
ferencd@0
|
163 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
164
|
|
ferencd@0
|
165 } // namespace maddy
|