summaryrefslogtreecommitdiff
path: root/Libraries
diff options
context:
space:
mode:
authorAnotherTest <ali.mpfard@gmail.com>2020-09-20 20:42:23 +0430
committerAndreas Kling <kling@serenityos.org>2020-09-27 21:14:18 +0200
commiteef794b8c645ea08fae3a9818c3a45ac5a4bccb4 (patch)
tree02906ee4071ca9168060e1213b2760231cc1c6b9 /Libraries
parent176a2f193c46951b4f9071cd6d02ec9d0f686770 (diff)
downloadserenity-eef794b8c645ea08fae3a9818c3a45ac5a4bccb4.zip
LibMarkdown: Parse paragraphs line-wise
This gets rid of the doubled-up checks in `Paragraph::parse()`, and makes a paragraph the last possible kind of block to be parsed.
Diffstat (limited to 'Libraries')
-rw-r--r--Libraries/LibMarkdown/Document.cpp26
-rw-r--r--Libraries/LibMarkdown/Paragraph.cpp60
-rw-r--r--Libraries/LibMarkdown/Paragraph.h25
3 files changed, 61 insertions, 50 deletions
diff --git a/Libraries/LibMarkdown/Document.cpp b/Libraries/LibMarkdown/Document.cpp
index ba3d244b74..3e036dab16 100644
--- a/Libraries/LibMarkdown/Document.cpp
+++ b/Libraries/LibMarkdown/Document.cpp
@@ -81,6 +81,7 @@ OwnPtr<Document> Document::parse(const StringView& str)
auto lines = lines_vec.begin();
auto document = make<Document>();
auto& blocks = document->m_blocks;
+ NonnullOwnPtrVector<Paragraph::Line> paragraph_lines;
while (true) {
if (lines.is_end())
@@ -91,11 +92,30 @@ OwnPtr<Document> Document::parse(const StringView& str)
continue;
}
- bool any = helper<Table>(lines, blocks) || helper<List>(lines, blocks) || helper<Paragraph>(lines, blocks)
- || helper<CodeBlock>(lines, blocks) || helper<Heading>(lines, blocks);
+ bool any = helper<Table>(lines, blocks) || helper<List>(lines, blocks) || helper<CodeBlock>(lines, blocks)
+ || helper<Heading>(lines, blocks);
+
+ if (any) {
+ if (!paragraph_lines.is_empty()) {
+ auto last_block = document->m_blocks.take_last();
+ auto paragraph = make<Paragraph>(move(paragraph_lines));
+ document->m_blocks.append(move(paragraph));
+ document->m_blocks.append(move(last_block));
+ paragraph_lines.clear();
+ }
+ continue;
+ }
- if (!any)
+ auto line = Paragraph::Line::parse(lines);
+ if (!line)
return nullptr;
+
+ paragraph_lines.append(line.release_nonnull());
+ }
+
+ if (!paragraph_lines.is_empty()) {
+ auto paragraph = make<Paragraph>(move(paragraph_lines));
+ document->m_blocks.append(move(paragraph));
}
return document;
diff --git a/Libraries/LibMarkdown/Paragraph.cpp b/Libraries/LibMarkdown/Paragraph.cpp
index f44da06fbb..0e2b7f9df4 100644
--- a/Libraries/LibMarkdown/Paragraph.cpp
+++ b/Libraries/LibMarkdown/Paragraph.cpp
@@ -33,7 +33,13 @@ String Paragraph::render_to_html() const
{
StringBuilder builder;
builder.appendf("<p>");
- builder.append(m_text.render_to_html());
+ bool first = true;
+ for (auto& line : m_lines) {
+ if (!first)
+ builder.append(' ');
+ first = false;
+ builder.append(line.text().render_to_html());
+ }
builder.appendf("</p>\n");
return builder.build();
}
@@ -41,58 +47,26 @@ String Paragraph::render_to_html() const
String Paragraph::render_for_terminal(size_t) const
{
StringBuilder builder;
- builder.append(m_text.render_for_terminal());
- builder.appendf("\n\n");
- return builder.build();
-}
-
-OwnPtr<Paragraph> Paragraph::parse(Vector<StringView>::ConstIterator& lines)
-{
- if (lines.is_end())
- return nullptr;
-
bool first = true;
- StringBuilder builder;
-
- while (true) {
- if (lines.is_end())
- break;
- StringView line = *lines;
- if (line.is_empty())
- break;
- char ch = line[0];
- // See if it looks like a blockquote
- // or like an indented block.
- if (ch == '>' || ch == ' ')
- break;
- if (line.length() > 1) {
- // See if it looks like a heading.
- if (ch == '#' && (line[1] == '#' || line[1] == ' '))
- break;
- // See if it looks like a code block.
- if (ch == '`' && line[1] == '`')
- break;
- // See if it looks like a list.
- if (ch == '*' || ch == '-')
- if (line[1] == ' ')
- break;
- }
-
+ for (auto& line : m_lines) {
if (!first)
builder.append(' ');
- builder.append(line);
first = false;
- ++lines;
+ builder.append(line.text().render_for_terminal());
}
+ builder.appendf("\n\n");
+ return builder.build();
+}
- if (first)
+OwnPtr<Paragraph::Line> Paragraph::Line::parse(Vector<StringView>::ConstIterator& lines)
+{
+ if (lines.is_end())
return nullptr;
- auto text = Text::parse(builder.build());
+ auto text = Text::parse(*lines++);
if (!text.has_value())
return nullptr;
- return make<Paragraph>(move(text.value()));
+ return make<Paragraph::Line>(text.release_value());
}
-
}
diff --git a/Libraries/LibMarkdown/Paragraph.h b/Libraries/LibMarkdown/Paragraph.h
index d5e63a03c2..98e9dc9b9e 100644
--- a/Libraries/LibMarkdown/Paragraph.h
+++ b/Libraries/LibMarkdown/Paragraph.h
@@ -26,6 +26,7 @@
#pragma once
+#include <AK/NonnullOwnPtrVector.h>
#include <AK/OwnPtr.h>
#include <LibMarkdown/Block.h>
#include <LibMarkdown/Text.h>
@@ -34,18 +35,34 @@ namespace Markdown {
class Paragraph final : public Block {
public:
- explicit Paragraph(Text&& text)
- : m_text(move(text))
+ class Line {
+ public:
+ explicit Line(Text&& text)
+ : m_text(move(text))
+ {
+ }
+
+ static OwnPtr<Line> parse(Vector<StringView>::ConstIterator& lines);
+ const Text& text() const { return m_text; }
+
+ private:
+ Text m_text;
+ };
+
+ Paragraph(NonnullOwnPtrVector<Line>&& lines)
+ : m_lines(move(lines))
{
}
+
virtual ~Paragraph() override { }
virtual String render_to_html() const override;
virtual String render_for_terminal(size_t view_width = 0) const override;
- static OwnPtr<Paragraph> parse(Vector<StringView>::ConstIterator& lines);
+
+ void add_line(NonnullOwnPtr<Line>&& line);
private:
- Text m_text;
+ NonnullOwnPtrVector<Line> m_lines;
};
}