1
0
Fork 0
mirror of https://github.com/LadybirdBrowser/ladybird.git synced 2025-06-10 18:10:56 +09:00

LibMarkdown: Add LineIterator

LineIterator wraps a vector's ConstIterator, to provide an iterator that
can work on indented container blocks (like lists and blockquotes).
This commit is contained in:
Peter Elliott 2021-09-19 11:14:18 -06:00 committed by Ali Mohammad Pur
parent cd560d3ae3
commit 10f6f6a723
Notes: sideshowbarker 2024-07-18 03:02:28 +09:00
16 changed files with 139 additions and 21 deletions

View file

@ -4,6 +4,7 @@ set(SOURCES
Document.cpp
Heading.cpp
HorizontalRule.cpp
LineIterator.cpp
List.cpp
Paragraph.cpp
Table.cpp

View file

@ -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 {};

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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));
}

View file

@ -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 {};

View file

@ -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;

View file

@ -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 {};

View file

@ -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);
};
}

View file

@ -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);
}
}

View file

@ -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 };
};
}

View file

@ -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;

View file

@ -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.

View file

@ -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;

View file

@ -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;