Coverage Report

Created: 2026-05-16 07:03

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/serenity/Userland/Libraries/LibGemini/Document.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2020, the SerenityOS developers.
3
 *
4
 * SPDX-License-Identifier: BSD-2-Clause
5
 */
6
7
#include <AK/ByteString.h>
8
#include <AK/NonnullOwnPtr.h>
9
#include <AK/NonnullRefPtr.h>
10
#include <AK/StringBuilder.h>
11
#include <AK/Vector.h>
12
#include <LibGemini/Document.h>
13
14
namespace Gemini {
15
16
ByteString Document::render_to_html() const
17
0
{
18
0
    StringBuilder html_builder;
19
0
    html_builder.append("<!DOCTYPE html>\n<html>\n"sv);
20
0
    html_builder.append("<head>\n<title>"sv);
21
0
    html_builder.append(m_url.serialize_path());
22
0
    html_builder.append("</title>\n</head>\n"sv);
23
0
    html_builder.append("<body>\n"sv);
24
0
    for (auto& line : m_lines) {
25
0
        html_builder.append(line->render_to_html());
26
0
    }
27
0
    html_builder.append("</body>"sv);
28
0
    html_builder.append("</html>"sv);
29
0
    return html_builder.to_byte_string();
30
0
}
31
32
NonnullRefPtr<Document> Document::parse(StringView lines, const URL::URL& url)
33
1.34k
{
34
1.34k
    auto document = adopt_ref(*new Document(url));
35
1.34k
    document->read_lines(lines);
36
1.34k
    return document;
37
1.34k
}
38
39
void Document::read_lines(StringView source)
40
1.34k
{
41
45.5M
    auto close_list_if_needed = [&] {
42
45.5M
        if (m_inside_unordered_list) {
43
11.8M
            m_inside_unordered_list = false;
44
11.8M
            m_lines.append(make<Control>(Control::UnorderedListEnd));
45
11.8M
        }
46
45.5M
    };
47
48
63.0M
    for (auto& line : source.lines()) {
49
63.0M
        if (line.starts_with("```"sv)) {
50
3.52k
            close_list_if_needed();
51
52
3.52k
            m_inside_preformatted_block = !m_inside_preformatted_block;
53
3.52k
            if (m_inside_preformatted_block) {
54
1.87k
                m_lines.append(make<Control>(Control::PreformattedStart));
55
1.87k
            } else {
56
1.64k
                m_lines.append(make<Control>(Control::PreformattedEnd));
57
1.64k
            }
58
3.52k
            continue;
59
3.52k
        }
60
61
63.0M
        if (m_inside_preformatted_block) {
62
5.65M
            m_lines.append(make<Preformatted>(move(line)));
63
5.65M
            continue;
64
5.65M
        }
65
66
57.3M
        if (line.starts_with('*')) {
67
11.8M
            if (!m_inside_unordered_list)
68
11.8M
                m_lines.append(make<Control>(Control::UnorderedListStart));
69
11.8M
            m_lines.append(make<UnorderedList>(move(line)));
70
11.8M
            m_inside_unordered_list = true;
71
11.8M
            continue;
72
11.8M
        }
73
74
45.5M
        close_list_if_needed();
75
76
45.5M
        if (line.starts_with("=>"sv)) {
77
9.49k
            m_lines.append(make<Link>(move(line), *this));
78
9.49k
            continue;
79
9.49k
        }
80
81
45.5M
        if (line.starts_with('#')) {
82
10.5k
            size_t level = 0;
83
21.4k
            while (line.length() > level && line[level] == '#')
84
10.8k
                ++level;
85
86
10.5k
            m_lines.append(make<Heading>(move(line), level));
87
10.5k
            continue;
88
10.5k
        }
89
90
45.5M
        m_lines.append(make<Text>(move(line)));
91
45.5M
    }
92
1.34k
}
93
94
}