/src/serenity/Userland/Libraries/LibMarkdown/Heading.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2019-2020, Sergey Bugaev <bugaevc@serenityos.org> |
3 | | * |
4 | | * SPDX-License-Identifier: BSD-2-Clause |
5 | | */ |
6 | | |
7 | | #include <AK/StringBuilder.h> |
8 | | #include <LibMarkdown/Heading.h> |
9 | | #include <LibMarkdown/Visitor.h> |
10 | | |
11 | | namespace Markdown { |
12 | | |
13 | | String Heading::render_to_html(bool) const |
14 | 0 | { |
15 | 0 | return String::formatted("<h{}>{}</h{}>\n", m_level, m_text.render_to_html(), m_level); |
16 | 0 | } |
17 | | |
18 | | String Heading::render_for_terminal(size_t) const |
19 | 0 | { |
20 | 0 | StringBuilder builder; |
21 | |
|
22 | 0 | builder.append("\033[0;31;1m\n"); |
23 | 0 | switch (m_level) { |
24 | 0 | case 1: |
25 | 0 | case 2: |
26 | 0 | builder.append(m_text.render_for_terminal().to_uppercase()); |
27 | 0 | builder.append("\033[0m\n"); |
28 | 0 | break; |
29 | 0 | default: |
30 | 0 | builder.append(m_text.render_for_terminal()); |
31 | 0 | builder.append("\033[0m\n"); |
32 | 0 | break; |
33 | 0 | } |
34 | | |
35 | 0 | return builder.build(); |
36 | 0 | } |
37 | | |
38 | | RecursionDecision Heading::walk(Visitor& visitor) const |
39 | 0 | { |
40 | 0 | RecursionDecision rd = visitor.visit(*this); |
41 | 0 | if (rd != RecursionDecision::Recurse) |
42 | 0 | return rd; |
43 | | |
44 | 0 | return m_text.walk(visitor); |
45 | 0 | } |
46 | | |
47 | | OwnPtr<Heading> Heading::parse(LineIterator& lines) |
48 | 13.9M | { |
49 | 13.9M | if (lines.is_end()) |
50 | 0 | return {}; |
51 | | |
52 | 13.9M | StringView line = *lines; |
53 | 13.9M | size_t indent = 0; |
54 | | |
55 | | // Allow for up to 3 spaces of indentation. |
56 | | // https://spec.commonmark.org/0.30/#example-68 |
57 | 13.9M | for (size_t i = 0; i < 3; ++i) { |
58 | 13.9M | if (line[i] != ' ') |
59 | 13.9M | break; |
60 | | |
61 | 24.3k | ++indent; |
62 | 24.3k | } |
63 | | |
64 | 13.9M | size_t level; |
65 | | |
66 | 16.1M | for (level = 0; indent + level < line.length(); level++) { |
67 | 14.8M | if (line[indent + level] != '#') |
68 | 12.6M | break; |
69 | 14.8M | } |
70 | | |
71 | 13.9M | if (!level || indent + level >= line.length() || line[indent + level] != ' ' || level > 6) |
72 | 12.9M | return {}; |
73 | | |
74 | 950k | StringView title_view = line.substring_view(indent + level + 1); |
75 | 950k | auto text = Text::parse(title_view); |
76 | 950k | auto heading = make<Heading>(move(text), level); |
77 | | |
78 | 950k | ++lines; |
79 | 950k | return heading; |
80 | 13.9M | } |
81 | | |
82 | | } |