Ver Fonte

LibHTML: Add a way to get a Document's title

You can now query Document::title() to get a String containing whatever
is inside the document's <title> tag.

In support of this, this patch adds the <html>, <head> and <title>
elements.
Andreas Kling há 5 anos atrás
pai
commit
b94c7665a9

+ 29 - 0
Libraries/LibHTML/DOM/Document.cpp

@@ -1,6 +1,9 @@
 #include <LibHTML/CSS/StyleResolver.h>
 #include <LibHTML/DOM/Document.h>
 #include <LibHTML/DOM/Element.h>
+#include <LibHTML/DOM/HTMLHeadElement.h>
+#include <LibHTML/DOM/HTMLHtmlElement.h>
+#include <LibHTML/DOM/HTMLTitleElement.h>
 #include <LibHTML/Layout/LayoutDocument.h>
 #include <stdio.h>
 
@@ -34,3 +37,29 @@ void Document::normalize()
     this->donate_all_children_to(body);
     this->append_child(html);
 }
+
+const HTMLHtmlElement* Document::document_element() const
+{
+    return static_cast<const HTMLHtmlElement*>(first_child_with_tag_name("html"));
+}
+
+const HTMLHeadElement* Document::head() const
+{
+    auto* html = document_element();
+    if (!html)
+        return nullptr;
+    return static_cast<const HTMLHeadElement*>(html->first_child_with_tag_name("head"));
+}
+
+String Document::title() const
+{
+    auto* head_element = head();
+    if (!head_element)
+        return {};
+
+    auto* title_element = static_cast<const HTMLTitleElement*>(head_element->first_child_with_tag_name("title"));
+    if (!title_element)
+        return {};
+
+    return title_element->text_content();
+}

+ 8 - 1
Libraries/LibHTML/DOM/Document.h

@@ -1,12 +1,14 @@
 #pragma once
 
-#include <AK/String.h>
 #include <AK/NonnullRefPtrVector.h>
 #include <AK/OwnPtr.h>
+#include <AK/String.h>
 #include <LibHTML/CSS/StyleResolver.h>
 #include <LibHTML/CSS/StyleSheet.h>
 #include <LibHTML/DOM/ParentNode.h>
 
+class HTMLHtmlElement;
+class HTMLHeadElement;
 class LayoutNode;
 class StyleResolver;
 class StyleSheet;
@@ -29,6 +31,11 @@ public:
     Node* hovered_node() { return m_hovered_node; }
     const Node* hovered_node() const { return m_hovered_node; }
 
+    const HTMLHtmlElement* document_element() const;
+    const HTMLHeadElement* head() const;
+
+    String title() const;
+
 private:
     OwnPtr<StyleResolver> m_style_resolver;
     NonnullRefPtrVector<StyleSheet> m_sheets;

+ 10 - 0
Libraries/LibHTML/DOM/HTMLHeadElement.cpp

@@ -0,0 +1,10 @@
+#include <LibHTML/DOM/HTMLHeadElement.h>
+
+HTMLHeadElement::HTMLHeadElement(Document& document, const String& tag_name)
+    : HTMLElement(document, tag_name)
+{
+}
+
+HTMLHeadElement::~HTMLHeadElement()
+{
+}

+ 9 - 0
Libraries/LibHTML/DOM/HTMLHeadElement.h

@@ -0,0 +1,9 @@
+#pragma once
+
+#include <LibHTML/DOM/HTMLElement.h>
+
+class HTMLHeadElement : public HTMLElement {
+public:
+    HTMLHeadElement(Document&, const String& tag_name);
+    virtual ~HTMLHeadElement() override;
+};

+ 10 - 0
Libraries/LibHTML/DOM/HTMLHtmlElement.cpp

@@ -0,0 +1,10 @@
+#include <LibHTML/DOM/HTMLHtmlElement.h>
+
+HTMLHtmlElement::HTMLHtmlElement(Document& document, const String& tag_name)
+    : HTMLElement(document, tag_name)
+{
+}
+
+HTMLHtmlElement::~HTMLHtmlElement()
+{
+}

+ 9 - 0
Libraries/LibHTML/DOM/HTMLHtmlElement.h

@@ -0,0 +1,9 @@
+#pragma once
+
+#include <LibHTML/DOM/HTMLElement.h>
+
+class HTMLHtmlElement : public HTMLElement {
+public:
+    HTMLHtmlElement(Document&, const String& tag_name);
+    virtual ~HTMLHtmlElement() override;
+};

+ 10 - 0
Libraries/LibHTML/DOM/HTMLTitleElement.cpp

@@ -0,0 +1,10 @@
+#include <LibHTML/DOM/HTMLTitleElement.h>
+
+HTMLTitleElement::HTMLTitleElement(Document& document, const String& tag_name)
+    : HTMLElement(document, tag_name)
+{
+}
+
+HTMLTitleElement::~HTMLTitleElement()
+{
+}

+ 9 - 0
Libraries/LibHTML/DOM/HTMLTitleElement.h

@@ -0,0 +1,9 @@
+#pragma once
+
+#include <LibHTML/DOM/HTMLElement.h>
+
+class HTMLTitleElement : public HTMLElement {
+public:
+    HTMLTitleElement(Document&, const String& tag_name);
+    virtual ~HTMLTitleElement() override;
+};

+ 9 - 0
Libraries/LibHTML/DOM/Node.h

@@ -46,6 +46,15 @@ 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;
+    }
+
 protected:
     Node(Document&, NodeType);
 

+ 1 - 0
Libraries/LibHTML/HtmlView.h

@@ -13,6 +13,7 @@ public:
     void set_document(Document*);
 
     Function<void(const String&)> on_link_click;
+    Function<void(const String&)> on_title_change;
 
 protected:
     HtmlView(GWidget* parent = nullptr);

+ 3 - 0
Libraries/LibHTML/Makefile.shared

@@ -5,6 +5,9 @@ LIBHTML_OBJS = \
     DOM/HTMLElement.o \
     DOM/HTMLAnchorElement.o \
     DOM/HTMLHeadingElement.o \
+    DOM/HTMLHeadElement.o \
+    DOM/HTMLHtmlElement.o \
+    DOM/HTMLTitleElement.o \
     DOM/Document.o \
     DOM/Text.o \
     CSS/Selector.o \

+ 9 - 0
Libraries/LibHTML/Parser/HTMLParser.cpp

@@ -2,7 +2,10 @@
 #include <AK/StringBuilder.h>
 #include <LibHTML/DOM/Element.h>
 #include <LibHTML/DOM/HTMLAnchorElement.h>
+#include <LibHTML/DOM/HTMLHeadElement.h>
 #include <LibHTML/DOM/HTMLHeadingElement.h>
+#include <LibHTML/DOM/HTMLHtmlElement.h>
+#include <LibHTML/DOM/HTMLTitleElement.h>
 #include <LibHTML/DOM/Text.h>
 #include <LibHTML/Parser/HTMLParser.h>
 #include <ctype.h>
@@ -13,6 +16,12 @@ static NonnullRefPtr<Element> create_element(Document& document, const String& t
     auto lowercase_tag_name = tag_name.to_lowercase();
     if (lowercase_tag_name == "a")
         return adopt(*new HTMLAnchorElement(document, tag_name));
+    if (lowercase_tag_name == "html")
+        return adopt(*new HTMLHtmlElement(document, tag_name));
+    if (lowercase_tag_name == "head")
+        return adopt(*new HTMLHeadElement(document, tag_name));
+    if (lowercase_tag_name == "title")
+        return adopt(*new HTMLTitleElement(document, tag_name));
     if (lowercase_tag_name == "h1"
         || lowercase_tag_name == "h2"
         || lowercase_tag_name == "h3"