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:
parent
cd560d3ae3
commit
10f6f6a723
Notes:
sideshowbarker
2024-07-18 03:02:28 +09:00
Author: https://github.com/petelliott
Commit: 10f6f6a723
Pull-request: https://github.com/SerenityOS/serenity/pull/10271
Reviewed-by: https://github.com/alimpfard
Reviewed-by: https://github.com/kleinesfilmroellchen
16 changed files with 139 additions and 21 deletions
|
@ -4,6 +4,7 @@ set(SOURCES
|
|||
Document.cpp
|
||||
Heading.cpp
|
||||
HorizontalRule.cpp
|
||||
LineIterator.cpp
|
||||
List.cpp
|
||||
Paragraph.cpp
|
||||
Table.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 {};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 {};
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
41
Userland/Libraries/LibMarkdown/LineIterator.cpp
Normal file
41
Userland/Libraries/LibMarkdown/LineIterator.cpp
Normal 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);
|
||||
}
|
||||
|
||||
}
|
75
Userland/Libraries/LibMarkdown/LineIterator.h
Normal file
75
Userland/Libraries/LibMarkdown/LineIterator.h
Normal 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 };
|
||||
};
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue