Serenity Operating System
1/*
2 * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <LibWeb/DOM/Element.h>
8#include <LibWeb/HTML/Parser/ListOfActiveFormattingElements.h>
9
10namespace Web::HTML {
11
12ListOfActiveFormattingElements::~ListOfActiveFormattingElements() = default;
13
14void ListOfActiveFormattingElements::visit_edges(JS::Cell::Visitor& visitor)
15{
16 for (auto& entry : m_entries)
17 visitor.visit(entry.element);
18}
19
20void ListOfActiveFormattingElements::add(DOM::Element& element)
21{
22 // FIXME: Implement the Noah's Ark clause https://html.spec.whatwg.org/multipage/parsing.html#push-onto-the-list-of-active-formatting-elements
23 m_entries.append({ element });
24}
25
26void ListOfActiveFormattingElements::add_marker()
27{
28 m_entries.append({ nullptr });
29}
30
31bool ListOfActiveFormattingElements::contains(const DOM::Element& element) const
32{
33 for (auto& entry : m_entries) {
34 if (entry.element.ptr() == &element)
35 return true;
36 }
37 return false;
38}
39
40DOM::Element* ListOfActiveFormattingElements::last_element_with_tag_name_before_marker(DeprecatedFlyString const& tag_name)
41{
42 for (ssize_t i = m_entries.size() - 1; i >= 0; --i) {
43 auto& entry = m_entries[i];
44 if (entry.is_marker())
45 return nullptr;
46 if (entry.element->local_name() == tag_name)
47 return entry.element.ptr();
48 }
49 return nullptr;
50}
51
52void ListOfActiveFormattingElements::remove(DOM::Element& element)
53{
54 m_entries.remove_first_matching([&](auto& entry) {
55 return entry.element.ptr() == &element;
56 });
57}
58
59void ListOfActiveFormattingElements::clear_up_to_the_last_marker()
60{
61 while (!m_entries.is_empty()) {
62 auto entry = m_entries.take_last();
63 if (entry.is_marker())
64 break;
65 }
66}
67
68Optional<size_t> ListOfActiveFormattingElements::find_index(DOM::Element const& element) const
69{
70 for (size_t i = 0; i < m_entries.size(); i++) {
71 if (m_entries[i].element.ptr() == &element)
72 return i;
73 }
74 return {};
75}
76
77void ListOfActiveFormattingElements::replace(DOM::Element& to_remove, DOM::Element& to_add)
78{
79 for (size_t i = 0; i < m_entries.size(); i++) {
80 if (m_entries[i].element.ptr() == &to_remove)
81 m_entries[i].element = JS::make_handle(to_add);
82 }
83}
84
85void ListOfActiveFormattingElements::insert_at(size_t index, DOM::Element& element)
86{
87 m_entries.insert(index, { element });
88}
89
90}