Serenity Operating System
at master 72 lines 2.9 kB view raw
1/* 2 * Copyright (c) 2020-2022, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <LibWeb/DOM/Element.h> 10#include <LibWeb/Forward.h> 11 12namespace Web::HTML { 13 14// https://html.spec.whatwg.org/multipage/parsing.html#stack-of-open-elements 15class StackOfOpenElements { 16public: 17 // Initially, the stack of open elements is empty. 18 // The stack grows downwards; the topmost node on the stack is the first one added to the stack, 19 // and the bottommost node of the stack is the most recently added node in the stack 20 // (notwithstanding when the stack is manipulated in a random access fashion as part of the handling for misnested tags). 21 22 StackOfOpenElements() = default; 23 ~StackOfOpenElements(); 24 25 DOM::Element& first() { return *m_elements.first(); } 26 DOM::Element& last() { return *m_elements.last(); } 27 28 bool is_empty() const { return m_elements.is_empty(); } 29 void push(JS::NonnullGCPtr<DOM::Element> element) { m_elements.append(element); } 30 JS::NonnullGCPtr<DOM::Element> pop() { return *m_elements.take_last(); } 31 void remove(DOM::Element const& element); 32 void replace(DOM::Element const& to_remove, JS::NonnullGCPtr<DOM::Element> to_add); 33 void insert_immediately_below(JS::NonnullGCPtr<DOM::Element> element_to_add, DOM::Element const& target); 34 35 const DOM::Element& current_node() const { return *m_elements.last(); } 36 DOM::Element& current_node() { return *m_elements.last(); } 37 38 bool has_in_scope(DeprecatedFlyString const& tag_name) const; 39 bool has_in_button_scope(DeprecatedFlyString const& tag_name) const; 40 bool has_in_table_scope(DeprecatedFlyString const& tag_name) const; 41 bool has_in_list_item_scope(DeprecatedFlyString const& tag_name) const; 42 bool has_in_select_scope(DeprecatedFlyString const& tag_name) const; 43 44 bool has_in_scope(const DOM::Element&) const; 45 46 bool contains(const DOM::Element&) const; 47 bool contains(DeprecatedFlyString const& tag_name) const; 48 49 auto const& elements() const { return m_elements; } 50 auto& elements() { return m_elements; } 51 52 void pop_until_an_element_with_tag_name_has_been_popped(DeprecatedFlyString const&); 53 54 JS::GCPtr<DOM::Element> topmost_special_node_below(DOM::Element const&); 55 56 struct LastElementResult { 57 JS::GCPtr<DOM::Element> element; 58 ssize_t index; 59 }; 60 LastElementResult last_element_with_tag_name(DeprecatedFlyString const&); 61 JS::GCPtr<DOM::Element> element_immediately_above(DOM::Element const&); 62 63 void visit_edges(JS::Cell::Visitor&); 64 65private: 66 bool has_in_scope_impl(DeprecatedFlyString const& tag_name, Vector<DeprecatedFlyString> const&) const; 67 bool has_in_scope_impl(const DOM::Element& target_node, Vector<DeprecatedFlyString> const&) const; 68 69 Vector<JS::NonnullGCPtr<DOM::Element>> m_elements; 70}; 71 72}