From 0270e2399781d885744c06ef72b069300f0d8828 Mon Sep 17 00:00:00 2001 From: Peter Elliott Date: Thu, 21 Apr 2022 23:34:09 -0600 Subject: [PATCH] LibMarkdown: Add support for indented code blocks --- Userland/Libraries/LibMarkdown/CodeBlock.cpp | 70 ++++++++++++++++++-- Userland/Libraries/LibMarkdown/CodeBlock.h | 3 + 2 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Userland/Libraries/LibMarkdown/CodeBlock.cpp b/Userland/Libraries/LibMarkdown/CodeBlock.cpp index 77fc4e3140..53e8e420f5 100644 --- a/Userland/Libraries/LibMarkdown/CodeBlock.cpp +++ b/Userland/Libraries/LibMarkdown/CodeBlock.cpp @@ -1,5 +1,6 @@ /* * Copyright (c) 2019-2020, Sergey Bugaev + * Copyright (c) 2022, Peter Elliott * * SPDX-License-Identifier: BSD-2-Clause */ @@ -76,16 +77,52 @@ RecursionDecision CodeBlock::walk(Visitor& visitor) const static Regex style_spec_re("\\s*([\\*_]*)\\s*([^\\*_\\s]*).*"); +static constexpr auto tick_tick_tick = "```"; + +static Optional line_block_prefix(StringView const& line) +{ + int characters = 0; + int indents = 0; + + for (char ch : line) { + if (indents == 4) + break; + + if (ch == ' ') { + ++characters; + ++indents; + } else if (ch == '\t') { + ++characters; + indents = 4; + } else { + break; + } + } + + if (indents == 4) + return characters; + + return {}; +} + OwnPtr CodeBlock::parse(LineIterator& lines) { if (lines.is_end()) return {}; - constexpr auto tick_tick_tick = "```"; - StringView line = *lines; - if (!line.starts_with(tick_tick_tick)) - return {}; + if (line.starts_with(tick_tick_tick)) + return parse_backticks(lines); + + if (line_block_prefix(line).has_value()) + return parse_indent(lines); + + return {}; +} + +OwnPtr CodeBlock::parse_backticks(LineIterator& lines) +{ + StringView line = *lines; // Our Markdown extension: we allow // specifying a style and a language @@ -124,4 +161,29 @@ OwnPtr CodeBlock::parse(LineIterator& lines) return make(language, style, builder.build()); } +OwnPtr CodeBlock::parse_indent(LineIterator& lines) +{ + bool first = true; + StringBuilder builder; + + while (true) { + if (lines.is_end()) + break; + StringView line = *lines; + + auto prefix_length = line_block_prefix(line); + if (!prefix_length.has_value()) + break; + + line = line.substring_view(prefix_length.value()); + ++lines; + + if (!first) + builder.append('\n'); + builder.append(line); + first = false; + } + + return make("", "", builder.build()); +} } diff --git a/Userland/Libraries/LibMarkdown/CodeBlock.h b/Userland/Libraries/LibMarkdown/CodeBlock.h index cac5d9418d..3a9ddc2b35 100644 --- a/Userland/Libraries/LibMarkdown/CodeBlock.h +++ b/Userland/Libraries/LibMarkdown/CodeBlock.h @@ -33,6 +33,9 @@ private: String m_code; String m_language; String m_style; + + static OwnPtr parse_backticks(LineIterator& lines); + static OwnPtr parse_indent(LineIterator& lines); }; }