Merge pull request '(FEAT): Block quotes implemented' (#42) from feature/blockquote into main
Reviewed-on: #42
This commit is contained in:
commit
436e08dbef
2
Makefile
2
Makefile
@ -40,7 +40,7 @@ $(BUILD_DIR)/%.o: $(LIB_DIR)/%.cpp
|
||||
$(CXX) $(CXXFLAGS) $(INCLUDES) -c $< -o $@ -pie
|
||||
|
||||
test: all
|
||||
./$(TARGET) test/journal.md -o output.html
|
||||
./$(TARGET) test/input.md -o output.html
|
||||
|
||||
clean:
|
||||
rm -rf $(BUILD_DIR) $(TARGET)
|
||||
|
||||
107
lib/parser.cpp
107
lib/parser.cpp
@ -8,6 +8,13 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
//
|
||||
// Please please PLEASSSEEEE ignore the "wetness" of this...
|
||||
// The architecture is under construction...
|
||||
//
|
||||
// wetness means not DRY, I just made it up :)
|
||||
//
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
|
||||
@ -103,7 +110,12 @@ std::unique_ptr<Node> Parser::ParseBlock() {
|
||||
return ParseImage();
|
||||
}
|
||||
|
||||
// 6. Parser paragraph
|
||||
// 6. Parse block quote
|
||||
if (c == '>') {
|
||||
return ParseBlockQuote();
|
||||
}
|
||||
|
||||
// 7. Parser paragraph
|
||||
return ParseParagraph();
|
||||
}
|
||||
|
||||
@ -201,6 +213,24 @@ std::unique_ptr<Node> Parser::ParseList(bool ordered) {
|
||||
return node;
|
||||
};
|
||||
|
||||
std::unique_ptr<Node> Parser::ParseBlockQuote() {
|
||||
auto node = std::make_unique<BlockQuoteNode>();
|
||||
|
||||
char c = Peek();
|
||||
while (c == '>') {
|
||||
Consume(); // Consume the '>' character
|
||||
ConsumeWhiteSpace(); // Consume whitespace
|
||||
c = Peek();
|
||||
}
|
||||
|
||||
auto children = ParseInlineBlockQuote();
|
||||
for (auto &child : children) {
|
||||
node->AddChild(std::move(child));
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
std::unique_ptr<Node> Parser::ParseCodeBlock() {
|
||||
auto node = std::make_unique<CodeBlockNode>();
|
||||
string str;
|
||||
@ -455,6 +485,81 @@ std::unique_ptr<Node> Parser::ParseInlineListContent() {
|
||||
return element;
|
||||
}
|
||||
|
||||
vector<std::unique_ptr<Node>> Parser::ParseInlineBlockQuote() {
|
||||
vector<std::unique_ptr<Node>> nodes;
|
||||
string str;
|
||||
|
||||
while (!IsEOF()) {
|
||||
char c = Peek();
|
||||
char c_next = Peek(1);
|
||||
|
||||
if (c == '\n') {
|
||||
if (c_next == '\n')
|
||||
break;
|
||||
|
||||
Consume(); // consume the '\n'
|
||||
|
||||
if (Peek() == '>') {
|
||||
Consume(); // consume the '>'
|
||||
str += " ";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (c == '!' && c_next == '[') {
|
||||
PushTextNode(nodes, str);
|
||||
auto node = ParseImage();
|
||||
if (!node->IsEmpty())
|
||||
nodes.push_back(std::move(node));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '[') {
|
||||
PushTextNode(nodes, str);
|
||||
auto node = ParseLink();
|
||||
if (!node->IsEmpty())
|
||||
nodes.push_back(std::move(node));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '*' && Peek(1) == '*' && Peek(2) == '*') {
|
||||
PushTextNode(nodes, str);
|
||||
auto node = ParseBoldItalic();
|
||||
if (!node->IsEmpty())
|
||||
nodes.push_back(std::move(node));
|
||||
continue;
|
||||
} else if (c == '*' && Peek(1) == '*') {
|
||||
PushTextNode(nodes, str);
|
||||
auto node = ParseBold();
|
||||
if (!node->IsEmpty())
|
||||
nodes.push_back(std::move(node));
|
||||
continue;
|
||||
} else if (c == '*') {
|
||||
PushTextNode(nodes, str);
|
||||
auto node = ParseItalic();
|
||||
if (!node->IsEmpty())
|
||||
nodes.push_back(std::move(node));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (c == '`') {
|
||||
PushTextNode(nodes, str);
|
||||
auto node = ParseCode();
|
||||
if (!node->IsEmpty())
|
||||
nodes.push_back(std::move(node));
|
||||
continue;
|
||||
}
|
||||
|
||||
// If a newline, use a space instead
|
||||
str += (c == '\n' ? ' ' : c); // TODO: Maybe we don't need this...?
|
||||
Consume();
|
||||
}
|
||||
|
||||
// Push the last node, if the string is not empty
|
||||
PushTextNode(nodes, str);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
std::unique_ptr<Node> Parser::ParseItalic() {
|
||||
string str;
|
||||
Consume(1);
|
||||
|
||||
@ -123,11 +123,13 @@ private:
|
||||
std::unique_ptr<Node> ParseHeading();
|
||||
std::unique_ptr<Node> ParseList(bool ordered);
|
||||
std::unique_ptr<Node> ParseCodeBlock();
|
||||
std::unique_ptr<Node> ParseBlockQuote();
|
||||
vector<std::unique_ptr<Node>> ParseInline();
|
||||
|
||||
// The only differences are the exit condition
|
||||
vector<std::unique_ptr<Node>> ParseInlineHeading();
|
||||
std::unique_ptr<Node> ParseInlineListContent();
|
||||
vector<std::unique_ptr<Node>> ParseInlineBlockQuote();
|
||||
|
||||
void PushTextNode(vector<std::unique_ptr<Node>> &nodes, string &str);
|
||||
|
||||
|
||||
@ -99,3 +99,15 @@ string ImageNode::ToHtml() const {
|
||||
ss << "<img src=\"" << this->src << "\" alt=\"" << this->alt << "\" />\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
string BlockQuoteNode::ToHtml() const {
|
||||
std::stringstream ss;
|
||||
|
||||
ss << "<blockquote>";
|
||||
for (const auto &child : this->GetChilren()) {
|
||||
ss << *child;
|
||||
}
|
||||
|
||||
ss << "</blockquote>\n";
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@ -143,4 +143,9 @@ public:
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
class BlockQuoteNode : public StructureNode {
|
||||
public:
|
||||
std::string ToHtml() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@ -1 +1,29 @@
|
||||

|
||||
hello world
|
||||
|
||||
>
|
||||
>
|
||||
>
|
||||
> hello world
|
||||
> hello world
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
> **a final line**
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
>
|
||||
|
||||
|
||||
> hello
|
||||
|
||||
|
||||
|
||||
hi mom
|
||||
|
||||
> hello world\n>\n>\n>\n> a new line
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user