diff options
author | AnotherTest <ali.mpfard@gmail.com> | 2020-09-20 20:42:23 +0430 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-27 21:14:18 +0200 |
commit | eef794b8c645ea08fae3a9818c3a45ac5a4bccb4 (patch) | |
tree | 02906ee4071ca9168060e1213b2760231cc1c6b9 /Libraries | |
parent | 176a2f193c46951b4f9071cd6d02ec9d0f686770 (diff) | |
download | serenity-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.cpp | 26 | ||||
-rw-r--r-- | Libraries/LibMarkdown/Paragraph.cpp | 60 | ||||
-rw-r--r-- | Libraries/LibMarkdown/Paragraph.h | 25 |
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; }; } |