Coverage Report

Created: 2025-12-18 07:52

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.26k
{
34
1.26k
    auto document = adopt_ref(*new Document(url));
35
1.26k
    document->read_lines(lines);
36
1.26k
    return document;
37
1.26k
}
38
39
void Document::read_lines(StringView source)
40
1.26k
{
41
46.9M
    auto close_list_if_needed = [&] {
42
46.9M
        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
46.9M
    };
47
48
63.5M
    for (auto& line : source.lines()) {
49
63.5M
        if (line.starts_with("```"sv)) {
50
5.30k
            close_list_if_needed();
51
52
5.30k
            m_inside_preformatted_block = !m_inside_preformatted_block;
53
5.30k
            if (m_inside_preformatted_block) {
54
2.76k
                m_lines.append(make<Control>(Control::PreformattedStart));
55
2.76k
            } else {
56
2.54k
                m_lines.append(make<Control>(Control::PreformattedEnd));
57
2.54k
            }
58
5.30k
            continue;
59
5.30k
        }
60
61
63.5M
        if (m_inside_preformatted_block) {
62
4.72M
            m_lines.append(make<Preformatted>(move(line)));
63
4.72M
            continue;
64
4.72M
        }
65
66
58.7M
        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
46.9M
        close_list_if_needed();
75
76
46.9M
        if (line.starts_with("=>"sv)) {
77
10.4k
            m_lines.append(make<Link>(move(line), *this));
78
10.4k
            continue;
79
10.4k
        }
80
81
46.9M
        if (line.starts_with('#')) {
82
13.0k
            size_t level = 0;
83
26.7k
            while (line.length() > level && line[level] == '#')
84
13.7k
                ++level;
85
86
13.0k
            m_lines.append(make<Heading>(move(line), level));
87
13.0k
            continue;
88
13.0k
        }
89
90
46.9M
        m_lines.append(make<Text>(move(line)));
91
46.9M
    }
92
1.26k
}
93
94
}