SyntaxHighlighter.cpp 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /*
  2. * Copyright (c) 2023, Maciej <sppmacd@pm.me>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <LibMarkdown/SyntaxHighlighter.h>
  7. namespace Markdown {
  8. Syntax::Language SyntaxHighlighter::language() const
  9. {
  10. return Syntax::Language::Markdown;
  11. }
  12. Optional<StringView> SyntaxHighlighter::comment_prefix() const
  13. {
  14. return {};
  15. }
  16. Optional<StringView> SyntaxHighlighter::comment_suffix() const
  17. {
  18. return {};
  19. }
  20. enum class Token {
  21. Default,
  22. Header,
  23. Code
  24. };
  25. void SyntaxHighlighter::rehighlight(Palette const& palette)
  26. {
  27. auto text = m_client->get_text();
  28. Vector<GUI::TextDocumentSpan> spans;
  29. auto append_header = [&](GUI::TextRange const& range) {
  30. Gfx::TextAttributes attributes;
  31. attributes.color = palette.base_text();
  32. attributes.bold = true;
  33. GUI::TextDocumentSpan span {
  34. .range = range,
  35. .attributes = attributes,
  36. .data = static_cast<u32>(Token::Header),
  37. .is_skippable = false
  38. };
  39. spans.append(span);
  40. };
  41. auto append_code_block = [&](GUI::TextRange const& range) {
  42. Gfx::TextAttributes attributes;
  43. attributes.color = palette.syntax_string();
  44. GUI::TextDocumentSpan span {
  45. .range = range,
  46. .attributes = attributes,
  47. .data = static_cast<u32>(Token::Code),
  48. .is_skippable = false
  49. };
  50. spans.append(span);
  51. };
  52. // Headers, code blocks
  53. {
  54. size_t line_index = 0;
  55. Optional<size_t> code_block_start;
  56. for (auto const& line : StringView(text).lines()) {
  57. if (line.starts_with("```"sv)) {
  58. if (code_block_start.has_value()) {
  59. append_code_block({ { *code_block_start, 0 }, { line_index, line.length() } });
  60. code_block_start = {};
  61. } else {
  62. code_block_start = line_index;
  63. }
  64. }
  65. if (!code_block_start.has_value()) {
  66. auto trimmed = line.trim_whitespace(TrimMode::Left);
  67. size_t indent = line.length() - trimmed.length();
  68. if (indent < 4 && trimmed.starts_with("#"sv)) {
  69. append_header({ { line_index, 0 }, { line_index, line.length() } });
  70. }
  71. }
  72. line_index++;
  73. }
  74. }
  75. // TODO: Highlight text nodes (em, strong, link, image)
  76. m_client->do_set_spans(spans);
  77. }
  78. Vector<SyntaxHighlighter::MatchingTokenPair> SyntaxHighlighter::matching_token_pairs_impl() const
  79. {
  80. return {};
  81. }
  82. bool SyntaxHighlighter::token_types_equal(u64 lhs, u64 rhs) const
  83. {
  84. return static_cast<Token>(lhs) == static_cast<Token>(rhs);
  85. }
  86. }