1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-19 21:55:07 +00:00
serenity/Userland/Libraries/LibMarkdown/Text.h
Liav A 22737b70bc LibMarkdown: Add render_for_raw_print methods to Node derived classes
This method will be used by the package manager code to render an actual
Port's name to raw text as it is stored as relative URL currently in the
AvailablePorts.md file.
2023-08-07 13:24:25 -06:00

212 lines
7.2 KiB
C++

/*
* Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org>
* Copyright (c) 2021, Peter Elliott <pelliott@serenityos.org>
* Copyright (c) 2022, the SerenityOS developers.
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/DeprecatedString.h>
#include <AK/Noncopyable.h>
#include <AK/OwnPtr.h>
#include <AK/RecursionDecision.h>
#include <AK/Vector.h>
#include <LibMarkdown/Forward.h>
namespace Markdown {
class Text final {
public:
class Node {
public:
virtual void render_to_html(StringBuilder& builder) const = 0;
virtual void render_for_terminal(StringBuilder& builder) const = 0;
virtual void render_for_raw_print(StringBuilder& builder) const = 0;
virtual size_t terminal_length() const = 0;
virtual RecursionDecision walk(Visitor&) const = 0;
virtual ~Node() = default;
};
class EmphasisNode : public Node {
public:
bool strong;
NonnullOwnPtr<Node> child;
EmphasisNode(bool strong, NonnullOwnPtr<Node> child)
: strong(strong)
, child(move(child))
{
}
virtual void render_to_html(StringBuilder& builder) const override;
virtual void render_for_terminal(StringBuilder& builder) const override;
virtual void render_for_raw_print(StringBuilder& builder) const override;
virtual size_t terminal_length() const override;
virtual RecursionDecision walk(Visitor&) const override;
};
class CodeNode : public Node {
public:
NonnullOwnPtr<Node> code;
CodeNode(NonnullOwnPtr<Node> code)
: code(move(code))
{
}
virtual void render_to_html(StringBuilder& builder) const override;
virtual void render_for_terminal(StringBuilder& builder) const override;
virtual void render_for_raw_print(StringBuilder& builder) const override;
virtual size_t terminal_length() const override;
virtual RecursionDecision walk(Visitor&) const override;
};
class BreakNode : public Node {
public:
virtual void render_to_html(StringBuilder& builder) const override;
virtual void render_for_terminal(StringBuilder& builder) const override;
virtual void render_for_raw_print(StringBuilder& builder) const override;
virtual size_t terminal_length() const override;
virtual RecursionDecision walk(Visitor&) const override;
};
class TextNode : public Node {
public:
DeprecatedString text;
bool collapsible;
TextNode(StringView text)
: text(text)
, collapsible(true)
{
}
TextNode(StringView text, bool collapsible)
: text(text)
, collapsible(collapsible)
{
}
virtual void render_to_html(StringBuilder& builder) const override;
virtual void render_for_terminal(StringBuilder& builder) const override;
virtual void render_for_raw_print(StringBuilder& builder) const override;
virtual size_t terminal_length() const override;
virtual RecursionDecision walk(Visitor&) const override;
};
class LinkNode : public Node {
public:
bool is_image;
NonnullOwnPtr<Node> text;
DeprecatedString href;
Optional<int> image_width;
Optional<int> image_height;
LinkNode(bool is_image, NonnullOwnPtr<Node> text, DeprecatedString href, Optional<int> image_width, Optional<int> image_height)
: is_image(is_image)
, text(move(text))
, href(move(href))
, image_width(image_width)
, image_height(image_height)
{
}
bool has_image_dimensions() const
{
return image_width.has_value() || image_height.has_value();
}
virtual void render_to_html(StringBuilder& builder) const override;
virtual void render_for_terminal(StringBuilder& builder) const override;
virtual void render_for_raw_print(StringBuilder& builder) const override;
virtual size_t terminal_length() const override;
virtual RecursionDecision walk(Visitor&) const override;
};
class MultiNode : public Node {
public:
Vector<NonnullOwnPtr<Node>> children;
virtual void render_to_html(StringBuilder& builder) const override;
virtual void render_for_terminal(StringBuilder& builder) const override;
virtual void render_for_raw_print(StringBuilder& builder) const override;
virtual size_t terminal_length() const override;
virtual RecursionDecision walk(Visitor&) const override;
};
class StrikeThroughNode : public Node {
public:
NonnullOwnPtr<Node> striked_text;
StrikeThroughNode(NonnullOwnPtr<Node> striked_text)
: striked_text(move(striked_text))
{
}
virtual void render_to_html(StringBuilder& builder) const override;
virtual void render_for_terminal(StringBuilder& builder) const override;
virtual void render_for_raw_print(StringBuilder& builder) const override;
virtual size_t terminal_length() const override;
virtual RecursionDecision walk(Visitor&) const override;
};
size_t terminal_length() const;
DeprecatedString render_to_html() const;
DeprecatedString render_for_terminal() const;
DeprecatedString render_for_raw_print() const;
RecursionDecision walk(Visitor&) const;
static Text parse(StringView);
private:
struct Token {
DeprecatedString data;
// Flanking basically means that a delimiter run has a non-whitespace,
// non-punctuation character on the corresponding side. For a more exact
// definition, see the CommonMark spec.
bool left_flanking;
bool right_flanking;
bool punct_before;
bool punct_after;
// is_run indicates that this token is a 'delimiter run'. A delimiter
// run occurs when several of the same syntactical character ('`', '_',
// or '*') occur in a row.
bool is_run;
char run_char() const
{
VERIFY(is_run);
return data[0];
}
char run_length() const
{
VERIFY(is_run);
return data.length();
}
bool is_space() const
{
return data[0] == ' ';
}
bool operator==(StringView str) const { return str == data; }
};
static Vector<Token> tokenize(StringView);
static bool can_open(Token const& opening);
static bool can_close_for(Token const& opening, Token const& closing);
static NonnullOwnPtr<MultiNode> parse_sequence(Vector<Token>::ConstIterator& tokens, bool in_link);
static NonnullOwnPtr<Node> parse_break(Vector<Token>::ConstIterator& tokens);
static NonnullOwnPtr<Node> parse_newline(Vector<Token>::ConstIterator& tokens);
static NonnullOwnPtr<Node> parse_emph(Vector<Token>::ConstIterator& tokens, bool in_link);
static NonnullOwnPtr<Node> parse_code(Vector<Token>::ConstIterator& tokens);
static NonnullOwnPtr<Node> parse_link(Vector<Token>::ConstIterator& tokens);
static NonnullOwnPtr<Node> parse_strike_through(Vector<Token>::ConstIterator& tokens);
OwnPtr<Node> m_node;
};
}