|
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 * OrderedListParser
|
|
ferencd@0
|
23 *
|
|
ferencd@0
|
24 * @class
|
|
ferencd@0
|
25 */
|
|
ferencd@0
|
26 class OrderedListParser : 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 OrderedListParser(
|
|
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 * An ordered list starts with `1. `.
|
|
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("^1\\. .*");
|
|
ferencd@0
|
58 return std::regex_match(line, re);
|
|
ferencd@0
|
59 }
|
|
ferencd@0
|
60
|
|
ferencd@0
|
61 /**
|
|
ferencd@0
|
62 * IsFinished
|
|
ferencd@0
|
63 *
|
|
ferencd@0
|
64 * @method
|
|
ferencd@0
|
65 * @return {bool}
|
|
ferencd@0
|
66 */
|
|
ferencd@0
|
67 bool
|
|
ferencd@0
|
68 IsFinished() const override
|
|
ferencd@0
|
69 {
|
|
ferencd@0
|
70 return this->isFinished;
|
|
ferencd@0
|
71 }
|
|
ferencd@0
|
72
|
|
ferencd@0
|
73 protected:
|
|
ferencd@0
|
74 bool
|
|
ferencd@0
|
75 isInlineBlockAllowed() const override
|
|
ferencd@0
|
76 {
|
|
ferencd@0
|
77 return true;
|
|
ferencd@0
|
78 }
|
|
ferencd@0
|
79
|
|
ferencd@0
|
80 bool
|
|
ferencd@0
|
81 isLineParserAllowed() const override
|
|
ferencd@0
|
82 {
|
|
ferencd@0
|
83 return true;
|
|
ferencd@0
|
84 }
|
|
ferencd@0
|
85
|
|
ferencd@0
|
86 void
|
|
ferencd@0
|
87 parseBlock(std::string& line) override
|
|
ferencd@0
|
88 {
|
|
ferencd@0
|
89 bool isStartOfNewListItem = this->isStartOfNewListItem(line);
|
|
ferencd@0
|
90 uint32_t indentation = getIndentationWidth(line);
|
|
ferencd@0
|
91
|
|
ferencd@0
|
92 static std::regex orderedlineRegex("^[1-9]+[0-9]*\\. ");
|
|
ferencd@0
|
93 line = std::regex_replace(line, orderedlineRegex, "");
|
|
ferencd@0
|
94 static std::regex unorderedlineRegex("^\\* ");
|
|
ferencd@0
|
95 line = std::regex_replace(line, unorderedlineRegex, "");
|
|
ferencd@0
|
96
|
|
ferencd@0
|
97 if (!this->isStarted)
|
|
ferencd@0
|
98 {
|
|
ferencd@0
|
99 line = "<ol><li>" + line;
|
|
ferencd@0
|
100 this->isStarted = true;
|
|
ferencd@0
|
101 return;
|
|
ferencd@0
|
102 }
|
|
ferencd@0
|
103
|
|
ferencd@0
|
104 if (indentation >= 2)
|
|
ferencd@0
|
105 {
|
|
ferencd@0
|
106 line = line.substr(2);
|
|
ferencd@0
|
107 return;
|
|
ferencd@0
|
108 }
|
|
ferencd@0
|
109
|
|
ferencd@0
|
110 if (
|
|
ferencd@0
|
111 line.empty() ||
|
|
ferencd@0
|
112 line.find("</li><li>") != std::string::npos ||
|
|
ferencd@0
|
113 line.find("</li></ol>") != std::string::npos ||
|
|
ferencd@0
|
114 line.find("</li></ul>") != std::string::npos
|
|
ferencd@0
|
115 )
|
|
ferencd@0
|
116 {
|
|
ferencd@0
|
117 line = "</li></ol>" + line;
|
|
ferencd@0
|
118 this->isFinished = true;
|
|
ferencd@0
|
119 return;
|
|
ferencd@0
|
120 }
|
|
ferencd@0
|
121
|
|
ferencd@0
|
122 if (isStartOfNewListItem)
|
|
ferencd@0
|
123 {
|
|
ferencd@0
|
124 line = "</li><li>" + line;
|
|
ferencd@0
|
125 }
|
|
ferencd@0
|
126 }
|
|
ferencd@0
|
127
|
|
ferencd@0
|
128 private:
|
|
ferencd@0
|
129 bool isStarted;
|
|
ferencd@0
|
130 bool isFinished;
|
|
ferencd@0
|
131
|
|
ferencd@0
|
132 bool
|
|
ferencd@0
|
133 isStartOfNewListItem(const std::string& line) const
|
|
ferencd@0
|
134 {
|
|
ferencd@0
|
135 static std::regex re("^(?:[1-9]+[0-9]*\\. |\\* ).*");
|
|
ferencd@0
|
136 return std::regex_match(line, re);
|
|
ferencd@0
|
137 }
|
|
ferencd@0
|
138 }; // class OrderedListParser
|
|
ferencd@0
|
139
|
|
ferencd@0
|
140 // -----------------------------------------------------------------------------
|
|
ferencd@0
|
141
|
|
ferencd@0
|
142 } // namespace maddy
|