1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 18:27:35 +00:00

LibMarkdown: Indent code blocks

This commit is contained in:
demostanis 2022-07-31 21:53:25 +02:00 committed by Brian Gianforcaro
parent 7537a045e5
commit 55b7f8ab27
3 changed files with 35 additions and 12 deletions

View file

@ -51,9 +51,13 @@ String CodeBlock::render_for_terminal(size_t) const
StringBuilder builder;
for (auto line : m_code.split('\n')) {
// Do not indent too much if we are in the synopsis
if (!(m_current_section && m_current_section->render_for_terminal().contains("SYNOPSIS"sv)))
builder.append(" "sv);
builder.append(" "sv);
builder.append(line);
builder.append("\n"sv);
builder.append("\x1b[0m\n"sv);
}
return builder.build();
@ -104,14 +108,14 @@ static Optional<int> line_block_prefix(StringView const& line)
return {};
}
OwnPtr<CodeBlock> CodeBlock::parse(LineIterator& lines)
OwnPtr<CodeBlock> CodeBlock::parse(LineIterator& lines, Heading* current_section)
{
if (lines.is_end())
return {};
StringView line = *lines;
if (open_fence_re.match(line).success)
return parse_backticks(lines);
return parse_backticks(lines, current_section);
if (line_block_prefix(line).has_value())
return parse_indent(lines);
@ -119,7 +123,7 @@ OwnPtr<CodeBlock> CodeBlock::parse(LineIterator& lines)
return {};
}
OwnPtr<CodeBlock> CodeBlock::parse_backticks(LineIterator& lines)
OwnPtr<CodeBlock> CodeBlock::parse_backticks(LineIterator& lines, Heading* current_section)
{
StringView line = *lines;
@ -160,7 +164,7 @@ OwnPtr<CodeBlock> CodeBlock::parse_backticks(LineIterator& lines)
builder.append('\n');
}
return make<CodeBlock>(language, style, builder.build());
return make<CodeBlock>(language, style, builder.build(), current_section);
}
OwnPtr<CodeBlock> CodeBlock::parse_indent(LineIterator& lines)
@ -183,6 +187,6 @@ OwnPtr<CodeBlock> CodeBlock::parse_indent(LineIterator& lines)
builder.append('\n');
}
return make<CodeBlock>("", "", builder.build());
return make<CodeBlock>("", "", builder.build(), nullptr);
}
}

View file

@ -9,6 +9,7 @@
#include <AK/OwnPtr.h>
#include <LibMarkdown/Block.h>
#include <LibMarkdown/Heading.h>
#include <LibMarkdown/LineIterator.h>
#include <LibMarkdown/Text.h>
@ -16,10 +17,11 @@ namespace Markdown {
class CodeBlock final : public Block {
public:
CodeBlock(String const& language, String const& style, String const& code)
CodeBlock(String const& language, String const& style, String const& code, Heading* current_section)
: m_code(move(code))
, m_language(language)
, m_style(style)
, m_current_section(current_section)
{
}
virtual ~CodeBlock() override = default;
@ -27,14 +29,15 @@ public:
virtual String render_to_html(bool tight = false) const override;
virtual String render_for_terminal(size_t view_width = 0) const override;
virtual RecursionDecision walk(Visitor&) const override;
static OwnPtr<CodeBlock> parse(LineIterator& lines);
static OwnPtr<CodeBlock> parse(LineIterator& lines, Heading* current_section);
private:
String m_code;
String m_language;
String m_style;
Heading* m_current_section;
static OwnPtr<CodeBlock> parse_backticks(LineIterator& lines);
static OwnPtr<CodeBlock> parse_backticks(LineIterator& lines, Heading* current_section);
static OwnPtr<CodeBlock> parse_indent(LineIterator& lines);
};

View file

@ -66,6 +66,16 @@ RecursionDecision ContainerBlock::walk(Visitor& visitor) const
return RecursionDecision::Continue;
}
template<class CodeBlock>
static bool try_parse_block(LineIterator& lines, NonnullOwnPtrVector<Block>& blocks, Heading* current_section)
{
OwnPtr<CodeBlock> block = CodeBlock::parse(lines, current_section);
if (!block)
return false;
blocks.append(block.release_nonnull());
return true;
}
template<typename BlockType>
static bool try_parse_block(LineIterator& lines, NonnullOwnPtrVector<Block>& blocks)
{
@ -81,6 +91,7 @@ OwnPtr<ContainerBlock> ContainerBlock::parse(LineIterator& lines)
NonnullOwnPtrVector<Block> blocks;
StringBuilder paragraph_text;
Heading* current_section;
auto flush_paragraph = [&] {
if (paragraph_text.is_empty())
@ -107,12 +118,17 @@ OwnPtr<ContainerBlock> ContainerBlock::parse(LineIterator& lines)
has_blank_lines = has_blank_lines || has_trailing_blank_lines;
}
bool any = try_parse_block<Table>(lines, blocks)
bool heading = false;
if ((heading = try_parse_block<Heading>(lines, blocks)))
current_section = dynamic_cast<Heading*>(&blocks.last());
bool any = heading
|| try_parse_block<Table>(lines, blocks)
|| try_parse_block<HorizontalRule>(lines, blocks)
|| try_parse_block<List>(lines, blocks)
|| try_parse_block<CodeBlock>(lines, blocks)
// CodeBlock needs to know the current section's name for proper indentation
|| try_parse_block<CodeBlock>(lines, blocks, current_section)
|| try_parse_block<CommentBlock>(lines, blocks)
|| try_parse_block<Heading>(lines, blocks)
|| try_parse_block<BlockQuote>(lines, blocks);
if (any) {