mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:27:35 +00:00
LibMarkdown+LibSyntax: Add a Markdown syntax highlighter
It currently supports only headers and code blocks.
This commit is contained in:
parent
416d6ab6c8
commit
cf52542fcf
8 changed files with 156 additions and 4 deletions
103
Userland/Libraries/LibMarkdown/SyntaxHighlighter.cpp
Normal file
103
Userland/Libraries/LibMarkdown/SyntaxHighlighter.cpp
Normal file
|
@ -0,0 +1,103 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Maciej <sppmacd@pm.me>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <LibMarkdown/SyntaxHighlighter.h>
|
||||
|
||||
namespace Markdown {
|
||||
|
||||
Syntax::Language SyntaxHighlighter::language() const
|
||||
{
|
||||
return Syntax::Language::Markdown;
|
||||
}
|
||||
|
||||
Optional<StringView> SyntaxHighlighter::comment_prefix() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
Optional<StringView> SyntaxHighlighter::comment_suffix() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
enum class Token {
|
||||
Default,
|
||||
Header,
|
||||
Code
|
||||
};
|
||||
|
||||
void SyntaxHighlighter::rehighlight(Palette const& palette)
|
||||
{
|
||||
auto text = m_client->get_text();
|
||||
|
||||
Vector<GUI::TextDocumentSpan> spans;
|
||||
|
||||
auto append_header = [&](GUI::TextRange const& range) {
|
||||
Gfx::TextAttributes attributes;
|
||||
attributes.color = palette.base_text();
|
||||
attributes.bold = true;
|
||||
GUI::TextDocumentSpan span {
|
||||
.range = range,
|
||||
.attributes = attributes,
|
||||
.data = static_cast<u32>(Token::Header),
|
||||
.is_skippable = false
|
||||
};
|
||||
spans.append(span);
|
||||
};
|
||||
|
||||
auto append_code_block = [&](GUI::TextRange const& range) {
|
||||
Gfx::TextAttributes attributes;
|
||||
attributes.color = palette.syntax_string();
|
||||
GUI::TextDocumentSpan span {
|
||||
.range = range,
|
||||
.attributes = attributes,
|
||||
.data = static_cast<u32>(Token::Code),
|
||||
.is_skippable = false
|
||||
};
|
||||
spans.append(span);
|
||||
};
|
||||
|
||||
// Headers, code blocks
|
||||
{
|
||||
size_t line_index = 0;
|
||||
Optional<size_t> code_block_start;
|
||||
for (auto const& line : StringView(text).lines()) {
|
||||
if (line.starts_with("```"sv)) {
|
||||
if (code_block_start.has_value()) {
|
||||
append_code_block({ { *code_block_start, 0 }, { line_index, line.length() } });
|
||||
code_block_start = {};
|
||||
} else {
|
||||
code_block_start = line_index;
|
||||
}
|
||||
}
|
||||
|
||||
if (!code_block_start.has_value()) {
|
||||
auto trimmed = line.trim_whitespace(TrimMode::Left);
|
||||
size_t indent = line.length() - trimmed.length();
|
||||
if (indent < 4 && trimmed.starts_with("#"sv)) {
|
||||
append_header({ { line_index, 0 }, { line_index, line.length() } });
|
||||
}
|
||||
}
|
||||
line_index++;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Highlight text nodes (em, strong, link, image)
|
||||
|
||||
m_client->do_set_spans(spans);
|
||||
}
|
||||
|
||||
Vector<SyntaxHighlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs_impl() const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
bool SyntaxHighlighter::token_types_equal(u64 lhs, u64 rhs) const
|
||||
{
|
||||
return static_cast<Token>(lhs) == static_cast<Token>(rhs);
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue