1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 19:37: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; StringBuilder builder;
for (auto line : m_code.split('\n')) { 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(" "sv);
builder.append(line); builder.append(line);
builder.append("\n"sv); builder.append("\x1b[0m\n"sv);
} }
return builder.build(); return builder.build();
@ -104,14 +108,14 @@ static Optional<int> line_block_prefix(StringView const& line)
return {}; return {};
} }
OwnPtr<CodeBlock> CodeBlock::parse(LineIterator& lines) OwnPtr<CodeBlock> CodeBlock::parse(LineIterator& lines, Heading* current_section)
{ {
if (lines.is_end()) if (lines.is_end())
return {}; return {};
StringView line = *lines; StringView line = *lines;
if (open_fence_re.match(line).success) if (open_fence_re.match(line).success)
return parse_backticks(lines); return parse_backticks(lines, current_section);
if (line_block_prefix(line).has_value()) if (line_block_prefix(line).has_value())
return parse_indent(lines); return parse_indent(lines);
@ -119,7 +123,7 @@ OwnPtr<CodeBlock> CodeBlock::parse(LineIterator& lines)
return {}; return {};
} }
OwnPtr<CodeBlock> CodeBlock::parse_backticks(LineIterator& lines) OwnPtr<CodeBlock> CodeBlock::parse_backticks(LineIterator& lines, Heading* current_section)
{ {
StringView line = *lines; StringView line = *lines;
@ -160,7 +164,7 @@ OwnPtr<CodeBlock> CodeBlock::parse_backticks(LineIterator& lines)
builder.append('\n'); 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) OwnPtr<CodeBlock> CodeBlock::parse_indent(LineIterator& lines)
@ -183,6 +187,6 @@ OwnPtr<CodeBlock> CodeBlock::parse_indent(LineIterator& lines)
builder.append('\n'); 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 <AK/OwnPtr.h>
#include <LibMarkdown/Block.h> #include <LibMarkdown/Block.h>
#include <LibMarkdown/Heading.h>
#include <LibMarkdown/LineIterator.h> #include <LibMarkdown/LineIterator.h>
#include <LibMarkdown/Text.h> #include <LibMarkdown/Text.h>
@ -16,10 +17,11 @@ namespace Markdown {
class CodeBlock final : public Block { class CodeBlock final : public Block {
public: 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_code(move(code))
, m_language(language) , m_language(language)
, m_style(style) , m_style(style)
, m_current_section(current_section)
{ {
} }
virtual ~CodeBlock() override = default; virtual ~CodeBlock() override = default;
@ -27,14 +29,15 @@ public:
virtual String render_to_html(bool tight = false) const override; virtual String render_to_html(bool tight = false) const override;
virtual String render_for_terminal(size_t view_width = 0) const override; virtual String render_for_terminal(size_t view_width = 0) const override;
virtual RecursionDecision walk(Visitor&) const override; virtual RecursionDecision walk(Visitor&) const override;
static OwnPtr<CodeBlock> parse(LineIterator& lines); static OwnPtr<CodeBlock> parse(LineIterator& lines, Heading* current_section);
private: private:
String m_code; String m_code;
String m_language; String m_language;
String m_style; 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); static OwnPtr<CodeBlock> parse_indent(LineIterator& lines);
}; };

View file

@ -66,6 +66,16 @@ RecursionDecision ContainerBlock::walk(Visitor& visitor) const
return RecursionDecision::Continue; 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> template<typename BlockType>
static bool try_parse_block(LineIterator& lines, NonnullOwnPtrVector<Block>& blocks) static bool try_parse_block(LineIterator& lines, NonnullOwnPtrVector<Block>& blocks)
{ {
@ -81,6 +91,7 @@ OwnPtr<ContainerBlock> ContainerBlock::parse(LineIterator& lines)
NonnullOwnPtrVector<Block> blocks; NonnullOwnPtrVector<Block> blocks;
StringBuilder paragraph_text; StringBuilder paragraph_text;
Heading* current_section;
auto flush_paragraph = [&] { auto flush_paragraph = [&] {
if (paragraph_text.is_empty()) 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; 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<HorizontalRule>(lines, blocks)
|| try_parse_block<List>(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<CommentBlock>(lines, blocks)
|| try_parse_block<Heading>(lines, blocks)
|| try_parse_block<BlockQuote>(lines, blocks); || try_parse_block<BlockQuote>(lines, blocks);
if (any) { if (any) {