summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Elliott <pelliott@ualberta.ca>2021-09-19 11:14:18 -0600
committerAli Mohammad Pur <Ali.mpfard@gmail.com>2021-10-05 13:27:25 +0330
commit10f6f6a723b2cec608d9499e27c28b7343d6e51f (patch)
tree89c3947d3ce78c57f10b74ea7f07097cef4d610f
parentcd560d3ae3c5dd618f54f802f1efffe633ba75a5 (diff)
downloadserenity-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.txt1
-rw-r--r--Userland/Libraries/LibMarkdown/CodeBlock.cpp2
-rw-r--r--Userland/Libraries/LibMarkdown/CodeBlock.h3
-rw-r--r--Userland/Libraries/LibMarkdown/ContainerBlock.cpp4
-rw-r--r--Userland/Libraries/LibMarkdown/ContainerBlock.h3
-rw-r--r--Userland/Libraries/LibMarkdown/Document.cpp9
-rw-r--r--Userland/Libraries/LibMarkdown/Heading.cpp2
-rw-r--r--Userland/Libraries/LibMarkdown/Heading.h3
-rw-r--r--Userland/Libraries/LibMarkdown/HorizontalRule.cpp2
-rw-r--r--Userland/Libraries/LibMarkdown/HorizontalRule.h3
-rw-r--r--Userland/Libraries/LibMarkdown/LineIterator.cpp41
-rw-r--r--Userland/Libraries/LibMarkdown/LineIterator.h75
-rw-r--r--Userland/Libraries/LibMarkdown/List.cpp2
-rw-r--r--Userland/Libraries/LibMarkdown/List.h3
-rw-r--r--Userland/Libraries/LibMarkdown/Table.cpp4
-rw-r--r--Userland/Libraries/LibMarkdown/Table.h3
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;