mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 20:07:35 +00:00
LibMarkdown: Indent code blocks
This commit is contained in:
parent
7537a045e5
commit
55b7f8ab27
3 changed files with 35 additions and 12 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
};
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue