diff options
author | Peter Elliott <pelliott@ualberta.ca> | 2021-09-19 11:14:18 -0600 |
---|---|---|
committer | Ali Mohammad Pur <Ali.mpfard@gmail.com> | 2021-10-05 13:27:25 +0330 |
commit | 10f6f6a723b2cec608d9499e27c28b7343d6e51f (patch) | |
tree | 89c3947d3ce78c57f10b74ea7f07097cef4d610f | |
parent | cd560d3ae3c5dd618f54f802f1efffe633ba75a5 (diff) | |
download | serenity-10f6f6a723b2cec608d9499e27c28b7343d6e51f.zip |
LibMarkdown: Add LineIterator
LineIterator wraps a vector's ConstIterator, to provide an iterator that
can work on indented container blocks (like lists and blockquotes).
-rw-r--r-- | Userland/Libraries/LibMarkdown/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/CodeBlock.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/CodeBlock.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/ContainerBlock.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/ContainerBlock.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/Document.cpp | 9 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/Heading.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/Heading.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/HorizontalRule.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/HorizontalRule.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/LineIterator.cpp | 41 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/LineIterator.h | 75 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/List.cpp | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/List.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/Table.cpp | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibMarkdown/Table.h | 3 |
16 files changed, 139 insertions, 21 deletions
diff --git a/Userland/Libraries/LibMarkdown/CMakeLists.txt b/Userland/Libraries/LibMarkdown/CMakeLists.txt index 6674966251..c079e687a4 100644 --- a/Userland/Libraries/LibMarkdown/CMakeLists.txt +++ b/Userland/Libraries/LibMarkdown/CMakeLists.txt @@ -4,6 +4,7 @@ set(SOURCES Document.cpp Heading.cpp HorizontalRule.cpp + LineIterator.cpp List.cpp Paragraph.cpp Table.cpp diff --git a/Userland/Libraries/LibMarkdown/CodeBlock.cpp b/Userland/Libraries/LibMarkdown/CodeBlock.cpp index 8229337280..e3e946dba0 100644 --- a/Userland/Libraries/LibMarkdown/CodeBlock.cpp +++ b/Userland/Libraries/LibMarkdown/CodeBlock.cpp @@ -56,7 +56,7 @@ String CodeBlock::render_for_terminal(size_t) const static Regex<ECMA262> style_spec_re("\\s*([\\*_]*)\\s*([^\\*_\\s]*).*"); -OwnPtr<CodeBlock> CodeBlock::parse(Vector<StringView>::ConstIterator& lines) +OwnPtr<CodeBlock> CodeBlock::parse(LineIterator& lines) { if (lines.is_end()) return {}; diff --git a/Userland/Libraries/LibMarkdown/CodeBlock.h b/Userland/Libraries/LibMarkdown/CodeBlock.h index 95f0fa1f78..7b353956d2 100644 --- a/Userland/Libraries/LibMarkdown/CodeBlock.h +++ b/Userland/Libraries/LibMarkdown/CodeBlock.h @@ -8,6 +8,7 @@ #include <AK/OwnPtr.h> #include <LibMarkdown/Block.h> +#include <LibMarkdown/LineIterator.h> #include <LibMarkdown/Text.h> namespace Markdown { @@ -24,7 +25,7 @@ public: virtual String render_to_html() const override; virtual String render_for_terminal(size_t view_width = 0) const override; - static OwnPtr<CodeBlock> parse(Vector<StringView>::ConstIterator& lines); + static OwnPtr<CodeBlock> parse(LineIterator& lines); private: String m_code; diff --git a/Userland/Libraries/LibMarkdown/ContainerBlock.cpp b/Userland/Libraries/LibMarkdown/ContainerBlock.cpp index 6acc5f3226..7585d635ee 100644 --- a/Userland/Libraries/LibMarkdown/ContainerBlock.cpp +++ b/Userland/Libraries/LibMarkdown/ContainerBlock.cpp @@ -39,7 +39,7 @@ String ContainerBlock::render_for_terminal(size_t view_width) const } template<typename BlockType> -static bool try_parse_block(Vector<StringView>::ConstIterator& lines, NonnullOwnPtrVector<Block>& blocks) +static bool try_parse_block(LineIterator& lines, NonnullOwnPtrVector<Block>& blocks) { OwnPtr<BlockType> block = BlockType::parse(lines); if (!block) @@ -48,7 +48,7 @@ static bool try_parse_block(Vector<StringView>::ConstIterator& lines, NonnullOwn return true; } -OwnPtr<ContainerBlock> ContainerBlock::parse(Vector<StringView>::ConstIterator& lines) +OwnPtr<ContainerBlock> ContainerBlock::parse(LineIterator& lines) { NonnullOwnPtrVector<Block> blocks; diff --git a/Userland/Libraries/LibMarkdown/ContainerBlock.h b/Userland/Libraries/LibMarkdown/ContainerBlock.h index bc7abf5058..682f850c69 100644 --- a/Userland/Libraries/LibMarkdown/ContainerBlock.h +++ b/Userland/Libraries/LibMarkdown/ContainerBlock.h @@ -10,6 +10,7 @@ #include <AK/OwnPtr.h> #include <AK/String.h> #include <LibMarkdown/Block.h> +#include <LibMarkdown/LineIterator.h> namespace Markdown { @@ -25,7 +26,7 @@ public: virtual String render_to_html() const override; virtual String render_for_terminal(size_t view_width = 0) const override; - static OwnPtr<ContainerBlock> parse(Vector<StringView>::ConstIterator& lines); + static OwnPtr<ContainerBlock> parse(LineIterator& lines); private: NonnullOwnPtrVector<Block> m_blocks; diff --git a/Userland/Libraries/LibMarkdown/Document.cpp b/Userland/Libraries/LibMarkdown/Document.cpp index 733e896f51..e1fd47cc9f 100644 --- a/Userland/Libraries/LibMarkdown/Document.cpp +++ b/Userland/Libraries/LibMarkdown/Document.cpp @@ -6,13 +6,8 @@ */ #include <AK/StringBuilder.h> -#include <LibMarkdown/CodeBlock.h> #include <LibMarkdown/Document.h> -#include <LibMarkdown/Heading.h> -#include <LibMarkdown/HorizontalRule.h> -#include <LibMarkdown/List.h> -#include <LibMarkdown/Paragraph.h> -#include <LibMarkdown/Table.h> +#include <LibMarkdown/LineIterator.h> namespace Markdown { @@ -49,7 +44,7 @@ String Document::render_for_terminal(size_t view_width) const OwnPtr<Document> Document::parse(const StringView& str) { const Vector<StringView> lines_vec = str.lines(); - auto lines = lines_vec.begin(); + LineIterator lines(lines_vec.begin()); return make<Document>(ContainerBlock::parse(lines)); } diff --git a/Userland/Libraries/LibMarkdown/Heading.cpp b/Userland/Libraries/LibMarkdown/Heading.cpp index 6c97ccb8aa..50fe6219f9 100644 --- a/Userland/Libraries/LibMarkdown/Heading.cpp +++ b/Userland/Libraries/LibMarkdown/Heading.cpp @@ -35,7 +35,7 @@ String Heading::render_for_terminal(size_t) const return builder.build(); } -OwnPtr<Heading> Heading::parse(Vector<StringView>::ConstIterator& lines) +OwnPtr<Heading> Heading::parse(LineIterator& lines) { if (lines.is_end()) return {}; diff --git a/Userland/Libraries/LibMarkdown/Heading.h b/Userland/Libraries/LibMarkdown/Heading.h index 596e0f2173..6378636475 100644 --- a/Userland/Libraries/LibMarkdown/Heading.h +++ b/Userland/Libraries/LibMarkdown/Heading.h @@ -10,6 +10,7 @@ #include <AK/StringView.h> #include <AK/Vector.h> #include <LibMarkdown/Block.h> +#include <LibMarkdown/LineIterator.h> #include <LibMarkdown/Text.h> namespace Markdown { @@ -26,7 +27,7 @@ public: virtual String render_to_html() const override; virtual String render_for_terminal(size_t view_width = 0) const override; - static OwnPtr<Heading> parse(Vector<StringView>::ConstIterator& lines); + static OwnPtr<Heading> parse(LineIterator& lines); private: Text m_text; diff --git a/Userland/Libraries/LibMarkdown/HorizontalRule.cpp b/Userland/Libraries/LibMarkdown/HorizontalRule.cpp index 190380c175..4f20d186ea 100644 --- a/Userland/Libraries/LibMarkdown/HorizontalRule.cpp +++ b/Userland/Libraries/LibMarkdown/HorizontalRule.cpp @@ -24,7 +24,7 @@ String HorizontalRule::render_for_terminal(size_t view_width) const return builder.to_string(); } -OwnPtr<HorizontalRule> HorizontalRule::parse(Vector<StringView>::ConstIterator& lines) +OwnPtr<HorizontalRule> HorizontalRule::parse(LineIterator& lines) { if (lines.is_end()) return {}; diff --git a/Userland/Libraries/LibMarkdown/HorizontalRule.h b/Userland/Libraries/LibMarkdown/HorizontalRule.h index 40ea3c577e..f4568ce214 100644 --- a/Userland/Libraries/LibMarkdown/HorizontalRule.h +++ b/Userland/Libraries/LibMarkdown/HorizontalRule.h @@ -10,6 +10,7 @@ #include <AK/StringView.h> #include <AK/Vector.h> #include <LibMarkdown/Block.h> +#include <LibMarkdown/LineIterator.h> namespace Markdown { @@ -22,7 +23,7 @@ public: virtual String render_to_html() const override; virtual String render_for_terminal(size_t view_width = 0) const override; - static OwnPtr<HorizontalRule> parse(Vector<StringView>::ConstIterator& lines); + static OwnPtr<HorizontalRule> parse(LineIterator& lines); }; } diff --git a/Userland/Libraries/LibMarkdown/LineIterator.cpp b/Userland/Libraries/LibMarkdown/LineIterator.cpp new file mode 100644 index 0000000000..6966112be8 --- /dev/null +++ b/Userland/Libraries/LibMarkdown/LineIterator.cpp @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <LibMarkdown/LineIterator.h> + +namespace Markdown { + +bool LineIterator::is_indented(StringView const& line) const +{ + if (line.is_whitespace()) + return true; + + if (line.length() < m_indent) + return false; + + for (size_t i = 0; i < m_indent; ++i) { + if (line[i] != ' ') + return false; + } + + return true; +} + +bool LineIterator::is_end() const +{ + return m_iterator.is_end() || (!m_ignore_prefix_mode && !is_indented(*m_iterator)); +} + +StringView LineIterator::operator*() const +{ + VERIFY(m_ignore_prefix_mode || is_indented(*m_iterator)); + if (m_iterator->is_whitespace()) + return *m_iterator; + + return m_iterator->substring_view(m_indent); +} + +} diff --git a/Userland/Libraries/LibMarkdown/LineIterator.h b/Userland/Libraries/LibMarkdown/LineIterator.h new file mode 100644 index 0000000000..04faad3b4e --- /dev/null +++ b/Userland/Libraries/LibMarkdown/LineIterator.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Iterator.h> +#include <AK/StringView.h> +#include <AK/Vector.h> + +namespace Markdown { + +template<typename T> +class FakePtr { +public: + FakePtr(T item) + : m_item(move(item)) + { + } + + T const* operator->() const { return &m_item; } + T* operator->() { return &m_item; } + +private: + T m_item; +}; + +class LineIterator { +public: + LineIterator(Vector<StringView>::ConstIterator const& lines, size_t indent = 0) + : m_iterator(lines) + , m_indent(indent) + { + } + + bool is_end() const; + StringView operator*() const; + + LineIterator operator++() + { + reset_ignore_prefix(); + ++m_iterator; + return *this; + } + + LineIterator operator++(int) + { + LineIterator tmp = *this; + reset_ignore_prefix(); + ++m_iterator; + return tmp; + } + + LineIterator operator+(ptrdiff_t delta) const { return LineIterator { m_iterator + delta, m_indent }; } + LineIterator operator-(ptrdiff_t delta) const { return LineIterator { m_iterator - delta, m_indent }; } + ptrdiff_t operator-(LineIterator other) const { return m_iterator - other.m_iterator; } + + FakePtr<StringView> operator->() const { return FakePtr<StringView>(operator*()); } + + size_t indent() const { return m_indent; } + void set_indent(size_t indent) { m_indent = indent; } + void ignore_next_prefix() { m_ignore_prefix_mode = true; } + +private: + void reset_ignore_prefix() { m_ignore_prefix_mode = false; } + bool is_indented(StringView const& line) const; + + Vector<StringView>::ConstIterator m_iterator; + size_t m_indent; + bool m_ignore_prefix_mode { false }; +}; + +} diff --git a/Userland/Libraries/LibMarkdown/List.cpp b/Userland/Libraries/LibMarkdown/List.cpp index 690753eaa9..4da8e18ba7 100644 --- a/Userland/Libraries/LibMarkdown/List.cpp +++ b/Userland/Libraries/LibMarkdown/List.cpp @@ -46,7 +46,7 @@ String List::render_for_terminal(size_t) const return builder.build(); } -OwnPtr<List> List::parse(Vector<StringView>::ConstIterator& lines) +OwnPtr<List> List::parse(LineIterator& lines) { Vector<Text> items; bool is_ordered = false; diff --git a/Userland/Libraries/LibMarkdown/List.h b/Userland/Libraries/LibMarkdown/List.h index ead37cffb1..10271403fd 100644 --- a/Userland/Libraries/LibMarkdown/List.h +++ b/Userland/Libraries/LibMarkdown/List.h @@ -9,6 +9,7 @@ #include <AK/OwnPtr.h> #include <AK/Vector.h> #include <LibMarkdown/Block.h> +#include <LibMarkdown/LineIterator.h> #include <LibMarkdown/Text.h> namespace Markdown { @@ -25,7 +26,7 @@ public: virtual String render_to_html() const override; virtual String render_for_terminal(size_t view_width = 0) const override; - static OwnPtr<List> parse(Vector<StringView>::ConstIterator& lines); + static OwnPtr<List> parse(LineIterator& lines); private: // TODO: List items should be considered blocks of their own kind. diff --git a/Userland/Libraries/LibMarkdown/Table.cpp b/Userland/Libraries/LibMarkdown/Table.cpp index 99c41f6787..692e2877bb 100644 --- a/Userland/Libraries/LibMarkdown/Table.cpp +++ b/Userland/Libraries/LibMarkdown/Table.cpp @@ -96,7 +96,7 @@ String Table::render_to_html() const return builder.to_string(); } -OwnPtr<Table> Table::parse(Vector<StringView>::ConstIterator& lines) +OwnPtr<Table> Table::parse(LineIterator& lines) { auto peek_it = lines; auto first_line = *peek_it; @@ -178,7 +178,7 @@ OwnPtr<Table> Table::parse(Vector<StringView>::ConstIterator& lines) size_t row_count = 0; ++lines; while (!lines.is_end()) { - auto& line = *lines; + auto line = *lines; if (!line.starts_with('|')) break; diff --git a/Userland/Libraries/LibMarkdown/Table.h b/Userland/Libraries/LibMarkdown/Table.h index 1ed2dbe464..76e0143c21 100644 --- a/Userland/Libraries/LibMarkdown/Table.h +++ b/Userland/Libraries/LibMarkdown/Table.h @@ -9,6 +9,7 @@ #include <AK/NonnullOwnPtrVector.h> #include <AK/OwnPtr.h> #include <LibMarkdown/Block.h> +#include <LibMarkdown/LineIterator.h> #include <LibMarkdown/Text.h> namespace Markdown { @@ -33,7 +34,7 @@ public: virtual String render_to_html() const override; virtual String render_for_terminal(size_t view_width = 0) const override; - static OwnPtr<Table> parse(Vector<StringView>::ConstIterator& lines); + static OwnPtr<Table> parse(LineIterator& lines); private: Vector<Column> m_columns; |