diff --git a/Libraries/LibHTML/DOM/Document.cpp b/Libraries/LibHTML/DOM/Document.cpp
index 0f8b1053ab..4543c897ae 100644
--- a/Libraries/LibHTML/DOM/Document.cpp
+++ b/Libraries/LibHTML/DOM/Document.cpp
@@ -41,7 +41,7 @@ void Document::normalize()
const HTMLHtmlElement* Document::document_element() const
{
- return static_cast(first_child_with_tag_name("html"));
+ return first_child_of_type();
}
const HTMLHeadElement* Document::head() const
@@ -49,7 +49,7 @@ const HTMLHeadElement* Document::head() const
auto* html = document_element();
if (!html)
return nullptr;
- return static_cast(html->first_child_with_tag_name("head"));
+ return html->first_child_of_type();
}
const HTMLBodyElement* Document::body() const
@@ -57,7 +57,7 @@ const HTMLBodyElement* Document::body() const
auto* html = document_element();
if (!html)
return nullptr;
- return static_cast(html->first_child_with_tag_name("body"));
+ return html->first_child_of_type();
}
String Document::title() const
@@ -66,7 +66,7 @@ String Document::title() const
if (!head_element)
return {};
- auto* title_element = static_cast(head_element->first_child_with_tag_name("title"));
+ auto* title_element = head_element->first_child_of_type();
if (!title_element)
return {};
diff --git a/Libraries/LibHTML/DOM/HTMLBodyElement.h b/Libraries/LibHTML/DOM/HTMLBodyElement.h
index b00a12fc9d..774db5deea 100644
--- a/Libraries/LibHTML/DOM/HTMLBodyElement.h
+++ b/Libraries/LibHTML/DOM/HTMLBodyElement.h
@@ -10,3 +10,9 @@ public:
virtual void parse_attribute(const String&, const String&) override;
virtual void apply_presentational_hints(StyleProperties&) const override;
};
+
+template<>
+inline bool is(const Node& node)
+{
+ return is(node) && to(node).tag_name().to_lowercase() == "body";
+}
diff --git a/Libraries/LibHTML/DOM/HTMLHeadElement.h b/Libraries/LibHTML/DOM/HTMLHeadElement.h
index 4586a26bf3..ad62b8a8e6 100644
--- a/Libraries/LibHTML/DOM/HTMLHeadElement.h
+++ b/Libraries/LibHTML/DOM/HTMLHeadElement.h
@@ -7,3 +7,9 @@ public:
HTMLHeadElement(Document&, const String& tag_name);
virtual ~HTMLHeadElement() override;
};
+
+template<>
+inline bool is(const Node& node)
+{
+ return is(node) && to(node).tag_name().to_lowercase() == "head";
+}
diff --git a/Libraries/LibHTML/DOM/HTMLTitleElement.h b/Libraries/LibHTML/DOM/HTMLTitleElement.h
index 4b0edf803a..9b39366ddf 100644
--- a/Libraries/LibHTML/DOM/HTMLTitleElement.h
+++ b/Libraries/LibHTML/DOM/HTMLTitleElement.h
@@ -7,3 +7,9 @@ public:
HTMLTitleElement(Document&, const String& tag_name);
virtual ~HTMLTitleElement() override;
};
+
+template<>
+inline bool is(const Node& node)
+{
+ return is(node) && to(node).tag_name().to_lowercase() == "title";
+}
diff --git a/Libraries/LibHTML/DOM/Node.h b/Libraries/LibHTML/DOM/Node.h
index 6a9208dd68..d4213f29a4 100644
--- a/Libraries/LibHTML/DOM/Node.h
+++ b/Libraries/LibHTML/DOM/Node.h
@@ -47,14 +47,8 @@ public:
virtual bool is_html_element() const { return false; }
- const Node* first_child_with_tag_name(const StringView& tag_name) const
- {
- for (auto* child = first_child(); child; child = child->next_sibling()) {
- if (child->tag_name() == tag_name)
- return child;
- }
- return nullptr;
- }
+ template
+ const T* first_child_of_type() const;
virtual void inserted_into(Node&) {}
virtual void removed_from(Node&) {}
@@ -106,9 +100,33 @@ inline const T& to(const Node& node)
return static_cast(node);
}
+template
+inline T* to(Node* node)
+{
+ ASSERT(is(node));
+ return static_cast(node);
+}
+
+template
+inline const T* to(const Node* node)
+{
+ ASSERT(is(node));
+ return static_cast(node);
+}
+
template
inline T& to(Node& node)
{
ASSERT(is(node));
return static_cast(node);
}
+
+template
+inline const T* Node::first_child_of_type() const
+{
+ for (auto* child = first_child(); child; child = child->next_sibling()) {
+ if (is(*child))
+ return to(child);
+ }
+ return nullptr;
+}