summaryrefslogtreecommitdiff
path: root/Libraries/LibWeb/DOM
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-03-07 10:32:51 +0100
committerAndreas Kling <kling@serenityos.org>2020-03-07 10:32:51 +0100
commit830a57c6b23430c749395811761252d1999f3559 (patch)
tree0bccfa6bc0ec8a39af0dab20633257df3384a4b3 /Libraries/LibWeb/DOM
parent7a6c4a72d5a7da31dbbd5178a469ae37ef68eaea (diff)
downloadserenity-830a57c6b23430c749395811761252d1999f3559.zip
LibWeb: Rename directory LibHTML => LibWeb
Let's rename this to LibWeb since it aims to provide more parts of the web platform than just HTML. :^)
Diffstat (limited to 'Libraries/LibWeb/DOM')
-rw-r--r--Libraries/LibWeb/DOM/CharacterData.cpp41
-rw-r--r--Libraries/LibWeb/DOM/CharacterData.h55
-rw-r--r--Libraries/LibWeb/DOM/Comment.cpp41
-rw-r--r--Libraries/LibWeb/DOM/Comment.h48
-rw-r--r--Libraries/LibWeb/DOM/Document.cpp335
-rw-r--r--Libraries/LibWeb/DOM/Document.h150
-rw-r--r--Libraries/LibWeb/DOM/DocumentFragment.h49
-rw-r--r--Libraries/LibWeb/DOM/DocumentType.cpp40
-rw-r--r--Libraries/LibWeb/DOM/DocumentType.h47
-rw-r--r--Libraries/LibWeb/DOM/Element.cpp221
-rw-r--r--Libraries/LibWeb/DOM/Element.h108
-rw-r--r--Libraries/LibWeb/DOM/ElementFactory.cpp88
-rw-r--r--Libraries/LibWeb/DOM/ElementFactory.h35
-rw-r--r--Libraries/LibWeb/DOM/HTMLAnchorElement.cpp40
-rw-r--r--Libraries/LibWeb/DOM/HTMLAnchorElement.h47
-rw-r--r--Libraries/LibWeb/DOM/HTMLBRElement.cpp46
-rw-r--r--Libraries/LibWeb/DOM/HTMLBRElement.h47
-rw-r--r--Libraries/LibWeb/DOM/HTMLBlinkElement.cpp57
-rw-r--r--Libraries/LibWeb/DOM/HTMLBlinkElement.h45
-rw-r--r--Libraries/LibWeb/DOM/HTMLBodyElement.cpp77
-rw-r--r--Libraries/LibWeb/DOM/HTMLBodyElement.h48
-rw-r--r--Libraries/LibWeb/DOM/HTMLElement.cpp40
-rw-r--r--Libraries/LibWeb/DOM/HTMLElement.h50
-rw-r--r--Libraries/LibWeb/DOM/HTMLFontElement.cpp53
-rw-r--r--Libraries/LibWeb/DOM/HTMLFontElement.h41
-rw-r--r--Libraries/LibWeb/DOM/HTMLFormElement.cpp86
-rw-r--r--Libraries/LibWeb/DOM/HTMLFormElement.h50
-rw-r--r--Libraries/LibWeb/DOM/HTMLHRElement.cpp40
-rw-r--r--Libraries/LibWeb/DOM/HTMLHRElement.h39
-rw-r--r--Libraries/LibWeb/DOM/HTMLHeadElement.cpp40
-rw-r--r--Libraries/LibWeb/DOM/HTMLHeadElement.h45
-rw-r--r--Libraries/LibWeb/DOM/HTMLHeadingElement.cpp40
-rw-r--r--Libraries/LibWeb/DOM/HTMLHeadingElement.h39
-rw-r--r--Libraries/LibWeb/DOM/HTMLHtmlElement.cpp40
-rw-r--r--Libraries/LibWeb/DOM/HTMLHtmlElement.h45
-rw-r--r--Libraries/LibWeb/DOM/HTMLImageElement.cpp127
-rw-r--r--Libraries/LibWeb/DOM/HTMLImageElement.h63
-rw-r--r--Libraries/LibWeb/DOM/HTMLInputElement.cpp82
-rw-r--r--Libraries/LibWeb/DOM/HTMLInputElement.h51
-rw-r--r--Libraries/LibWeb/DOM/HTMLLinkElement.cpp66
-rw-r--r--Libraries/LibWeb/DOM/HTMLLinkElement.h51
-rw-r--r--Libraries/LibWeb/DOM/HTMLStyleElement.cpp65
-rw-r--r--Libraries/LibWeb/DOM/HTMLStyleElement.h47
-rw-r--r--Libraries/LibWeb/DOM/HTMLTitleElement.cpp40
-rw-r--r--Libraries/LibWeb/DOM/HTMLTitleElement.h45
-rw-r--r--Libraries/LibWeb/DOM/Node.cpp120
-rw-r--r--Libraries/LibWeb/DOM/Node.h191
-rw-r--r--Libraries/LibWeb/DOM/ParentNode.cpp28
-rw-r--r--Libraries/LibWeb/DOM/ParentNode.h59
-rw-r--r--Libraries/LibWeb/DOM/Text.cpp46
-rw-r--r--Libraries/LibWeb/DOM/Text.h51
51 files changed, 3445 insertions, 0 deletions
diff --git a/Libraries/LibWeb/DOM/CharacterData.cpp b/Libraries/LibWeb/DOM/CharacterData.cpp
new file mode 100644
index 0000000000..a7fa15eb1d
--- /dev/null
+++ b/Libraries/LibWeb/DOM/CharacterData.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/CharacterData.h>
+
+namespace Web {
+
+CharacterData::CharacterData(Document& document, NodeType type, const String& data)
+ : Node(document, type)
+ , m_data(data)
+{
+}
+
+CharacterData::~CharacterData()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/CharacterData.h b/Libraries/LibWeb/DOM/CharacterData.h
new file mode 100644
index 0000000000..dece5fe338
--- /dev/null
+++ b/Libraries/LibWeb/DOM/CharacterData.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <LibWeb/DOM/Node.h>
+
+namespace Web {
+
+class CharacterData : public Node {
+public:
+ virtual ~CharacterData() override;
+
+ const String& data() const { return m_data; }
+
+ virtual String text_content() const override { return m_data; }
+
+protected:
+ explicit CharacterData(Document&, NodeType, const String&);
+
+private:
+ String m_data;
+};
+
+template<>
+inline bool is<CharacterData>(const Node& node)
+{
+ return node.is_character_data();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Comment.cpp b/Libraries/LibWeb/DOM/Comment.cpp
new file mode 100644
index 0000000000..0bd30e008e
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Comment.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/Comment.h>
+#include <LibWeb/Layout/LayoutText.h>
+
+namespace Web {
+
+Comment::Comment(Document& document, const String& data)
+ : CharacterData(document, NodeType::COMMENT_NODE, data)
+{
+}
+
+Comment::~Comment()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Comment.h b/Libraries/LibWeb/DOM/Comment.h
new file mode 100644
index 0000000000..8530ad9191
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Comment.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <LibWeb/DOM/CharacterData.h>
+
+namespace Web {
+
+class Comment final : public CharacterData {
+public:
+ explicit Comment(Document&, const String&);
+ virtual ~Comment() override;
+
+ virtual String tag_name() const override { return "#comment"; }
+};
+
+template<>
+inline bool is<Comment>(const Node& node)
+{
+ return node.is_comment();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Document.cpp b/Libraries/LibWeb/DOM/Document.cpp
new file mode 100644
index 0000000000..6b2f11e81a
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Document.cpp
@@ -0,0 +1,335 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/FileSystemPath.h>
+#include <AK/StringBuilder.h>
+#include <LibCore/Timer.h>
+#include <LibGUI/Application.h>
+#include <LibWeb/CSS/StyleResolver.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/DocumentType.h>
+#include <LibWeb/DOM/Element.h>
+#include <LibWeb/DOM/ElementFactory.h>
+#include <LibWeb/DOM/HTMLBodyElement.h>
+#include <LibWeb/DOM/HTMLHeadElement.h>
+#include <LibWeb/DOM/HTMLHtmlElement.h>
+#include <LibWeb/DOM/HTMLTitleElement.h>
+#include <LibWeb/Frame.h>
+#include <LibWeb/HtmlView.h>
+#include <LibWeb/Layout/LayoutDocument.h>
+#include <LibWeb/Layout/LayoutTreeBuilder.h>
+#include <stdio.h>
+
+namespace Web {
+
+Document::Document()
+ : ParentNode(*this, NodeType::DOCUMENT_NODE)
+ , m_style_resolver(make<StyleResolver>(*this))
+{
+ m_style_update_timer = Core::Timer::construct();
+ m_style_update_timer->set_single_shot(true);
+ m_style_update_timer->set_interval(0);
+ m_style_update_timer->on_timeout = [this] {
+ update_style();
+ };
+}
+
+Document::~Document()
+{
+}
+
+void Document::schedule_style_update()
+{
+ if (m_style_update_timer->is_active())
+ return;
+ m_style_update_timer->start();
+}
+
+bool Document::is_child_allowed(const Node& node) const
+{
+ switch (node.type()) {
+ case NodeType::DOCUMENT_NODE:
+ case NodeType::TEXT_NODE:
+ return false;
+ case NodeType::COMMENT_NODE:
+ return true;
+ case NodeType::DOCUMENT_TYPE_NODE:
+ return !first_child_of_type<DocumentType>();
+ case NodeType::ELEMENT_NODE:
+ return !first_child_of_type<Element>();
+ default:
+ return false;
+ }
+}
+
+void Document::fixup()
+{
+ if (!first_child() || !is<DocumentType>(*first_child()))
+ prepend_child(adopt(*new DocumentType(*this)));
+
+ if (is<HTMLHtmlElement>(first_child()->next_sibling()))
+ return;
+
+ auto body = create_element(*this, "body");
+ auto html = create_element(*this, "html");
+ html->append_child(body);
+ this->donate_all_children_to(body);
+ this->append_child(html);
+}
+
+const HTMLHtmlElement* Document::document_element() const
+{
+ return first_child_of_type<HTMLHtmlElement>();
+}
+
+const HTMLHeadElement* Document::head() const
+{
+ auto* html = document_element();
+ if (!html)
+ return nullptr;
+ return html->first_child_of_type<HTMLHeadElement>();
+}
+
+const HTMLBodyElement* Document::body() const
+{
+ auto* html = document_element();
+ if (!html)
+ return nullptr;
+ return html->first_child_of_type<HTMLBodyElement>();
+}
+
+String Document::title() const
+{
+ auto* head_element = head();
+ if (!head_element)
+ return {};
+
+ auto* title_element = head_element->first_child_of_type<HTMLTitleElement>();
+ if (!title_element)
+ return {};
+
+ return title_element->text_content();
+}
+
+void Document::attach_to_frame(Badge<Frame>, Frame& frame)
+{
+ m_frame = frame.make_weak_ptr();
+ layout();
+}
+
+void Document::detach_from_frame(Badge<Frame>, Frame&)
+{
+ m_layout_root = nullptr;
+ m_frame = nullptr;
+}
+
+Color Document::background_color(const Palette& palette) const
+{
+ auto default_color = palette.base();
+ auto* body_element = body();
+ if (!body_element)
+ return default_color;
+
+ auto* body_layout_node = body_element->layout_node();
+ if (!body_layout_node)
+ return default_color;
+
+ auto background_color = body_layout_node->style().property(CSS::PropertyID::BackgroundColor);
+ if (!background_color.has_value() || !background_color.value()->is_color())
+ return default_color;
+
+ return background_color.value()->to_color(*this);
+}
+
+RefPtr<Gfx::Bitmap> Document::background_image() const
+{
+ auto* body_element = body();
+ if (!body_element)
+ return {};
+
+ auto* body_layout_node = body_element->layout_node();
+ if (!body_layout_node)
+ return {};
+
+ auto background_image = body_layout_node->style().property(CSS::PropertyID::BackgroundImage);
+ if (!background_image.has_value() || !background_image.value()->is_image())
+ return {};
+
+ auto& image_value = static_cast<const ImageStyleValue&>(*background_image.value());
+ if (!image_value.bitmap())
+ return {};
+
+ return *image_value.bitmap();
+}
+
+URL Document::complete_url(const String& string) const
+{
+ return m_url.complete_url(string);
+}
+
+void Document::force_layout()
+{
+ m_layout_root = nullptr;
+ layout();
+}
+
+void Document::layout()
+{
+ if (!m_layout_root) {
+ LayoutTreeBuilder tree_builder;
+ m_layout_root = tree_builder.build(*this);
+ }
+ m_layout_root->layout();
+ m_layout_root->set_needs_display();
+}
+
+void Document::update_style()
+{
+ for_each_in_subtree_of_type<Element>([&](auto& element) {
+ if (element.needs_style_update())
+ element.recompute_style();
+ return IterationDecision::Continue;
+ });
+ update_layout();
+}
+
+void Document::update_layout()
+{
+ if (!frame())
+ return;
+
+ layout();
+ if (on_layout_updated)
+ on_layout_updated();
+}
+
+RefPtr<LayoutNode> Document::create_layout_node(const StyleProperties*) const
+{
+ return adopt(*new LayoutDocument(*this, StyleProperties::create()));
+}
+
+void Document::set_link_color(Color color)
+{
+ m_link_color = color;
+}
+
+void Document::set_active_link_color(Color color)
+{
+ m_active_link_color = color;
+}
+
+void Document::set_visited_link_color(Color color)
+{
+ m_visited_link_color = color;
+}
+
+const LayoutDocument* Document::layout_node() const
+{
+ return static_cast<const LayoutDocument*>(Node::layout_node());
+}
+
+LayoutDocument* Document::layout_node()
+{
+ return static_cast<LayoutDocument*>(Node::layout_node());
+}
+
+void Document::set_inspected_node(Node* node)
+{
+ if (m_inspected_node == node)
+ return;
+
+ if (m_inspected_node && m_inspected_node->layout_node())
+ m_inspected_node->layout_node()->set_needs_display();
+
+ m_inspected_node = node;
+
+ if (m_inspected_node && m_inspected_node->layout_node())
+ m_inspected_node->layout_node()->set_needs_display();
+}
+
+void Document::set_hovered_node(Node* node)
+{
+ if (m_hovered_node == node)
+ return;
+
+ RefPtr<Node> old_hovered_node = move(m_hovered_node);
+ m_hovered_node = node;
+
+ invalidate_style();
+}
+
+const Element* Document::get_element_by_id(const String& id) const
+{
+ const Element* found_element = nullptr;
+ for_each_in_subtree_of_type<Element>([&](auto& element) {
+ if (element.attribute("id") == id) {
+ found_element = &element;
+ return IterationDecision::Break;
+ }
+ return IterationDecision::Continue;
+ });
+ return found_element;
+}
+
+Vector<const Element*> Document::get_elements_by_name(const String& name) const
+{
+ Vector<const Element*> elements;
+ for_each_in_subtree_of_type<Element>([&](auto& element) {
+ if (element.attribute("name") == name)
+ elements.append(&element);
+ return IterationDecision::Continue;
+ });
+ return elements;
+}
+
+Color Document::link_color() const
+{
+ if (m_link_color.has_value())
+ return m_link_color.value();
+ if (!frame())
+ return Color::Blue;
+ return frame()->html_view()->palette().link();
+}
+
+Color Document::active_link_color() const
+{
+ if (m_active_link_color.has_value())
+ return m_active_link_color.value();
+ if (!frame())
+ return Color::Red;
+ return frame()->html_view()->palette().active_link();
+}
+
+Color Document::visited_link_color() const
+{
+ if (m_visited_link_color.has_value())
+ return m_visited_link_color.value();
+ if (!frame())
+ return Color::Magenta;
+ return frame()->html_view()->palette().visited_link();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h
new file mode 100644
index 0000000000..aa7d3e2014
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Document.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Function.h>
+#include <AK/NonnullRefPtrVector.h>
+#include <AK/OwnPtr.h>
+#include <AK/String.h>
+#include <AK/URL.h>
+#include <AK/WeakPtr.h>
+#include <LibCore/Forward.h>
+#include <LibWeb/CSS/StyleResolver.h>
+#include <LibWeb/CSS/StyleSheet.h>
+#include <LibWeb/DOM/ParentNode.h>
+
+namespace Web {
+
+class Frame;
+class HTMLBodyElement;
+class HTMLHtmlElement;
+class HTMLHeadElement;
+class LayoutDocument;
+class LayoutNode;
+class StyleResolver;
+class StyleSheet;
+
+class Document : public ParentNode {
+public:
+ Document();
+ virtual ~Document() override;
+
+ void set_url(const URL& url) { m_url = url; }
+ const URL& url() const { return m_url; }
+
+ URL complete_url(const String&) const;
+
+ void fixup();
+
+ StyleResolver& style_resolver() { return *m_style_resolver; }
+ const StyleResolver& style_resolver() const { return *m_style_resolver; }
+
+ void add_sheet(const StyleSheet& sheet) { m_sheets.append(sheet); }
+ const NonnullRefPtrVector<StyleSheet>& stylesheets() const { return m_sheets; }
+
+ virtual String tag_name() const override { return "#document"; }
+
+ void set_hovered_node(Node*);
+ Node* hovered_node() { return m_hovered_node; }
+ const Node* hovered_node() const { return m_hovered_node; }
+
+ void set_inspected_node(Node*);
+ Node* inspected_node() { return m_inspected_node; }
+ const Node* inspected_node() const { return m_inspected_node; }
+
+ const HTMLHtmlElement* document_element() const;
+ const HTMLHeadElement* head() const;
+ const HTMLBodyElement* body() const;
+
+ String title() const;
+
+ void attach_to_frame(Badge<Frame>, Frame&);
+ void detach_from_frame(Badge<Frame>, Frame&);
+
+ Frame* frame() { return m_frame.ptr(); }
+ const Frame* frame() const { return m_frame.ptr(); }
+
+ Color background_color(const Gfx::Palette&) const;
+ RefPtr<Gfx::Bitmap> background_image() const;
+
+ Color link_color() const;
+ void set_link_color(Color);
+
+ Color active_link_color() const;
+ void set_active_link_color(Color);
+
+ Color visited_link_color() const;
+ void set_visited_link_color(Color);
+
+ void layout();
+ void force_layout();
+
+ void update_style();
+ void update_layout();
+ Function<void()> on_layout_updated;
+
+ virtual bool is_child_allowed(const Node&) const override;
+
+ const LayoutDocument* layout_node() const;
+ LayoutDocument* layout_node();
+
+ void schedule_style_update();
+
+ const Element* get_element_by_id(const String&) const;
+ Vector<const Element*> get_elements_by_name(const String&) const;
+
+ const String& source() const { return m_source; }
+ void set_source(const String& source) { m_source = source; }
+
+private:
+ virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+
+ OwnPtr<StyleResolver> m_style_resolver;
+ NonnullRefPtrVector<StyleSheet> m_sheets;
+ RefPtr<Node> m_hovered_node;
+ RefPtr<Node> m_inspected_node;
+ WeakPtr<Frame> m_frame;
+ URL m_url;
+
+ RefPtr<LayoutDocument> m_layout_root;
+
+ Optional<Color> m_link_color;
+ Optional<Color> m_active_link_color;
+ Optional<Color> m_visited_link_color;
+
+ RefPtr<Core::Timer> m_style_update_timer;
+
+ String m_source;
+};
+
+template<>
+inline bool is<Document>(const Node& node)
+{
+ return node.is_document();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/DocumentFragment.h b/Libraries/LibWeb/DOM/DocumentFragment.h
new file mode 100644
index 0000000000..55e51feec4
--- /dev/null
+++ b/Libraries/LibWeb/DOM/DocumentFragment.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/ParentNode.h>
+
+namespace Web {
+
+class DocumentFragment : public ParentNode {
+public:
+ DocumentFragment(Document& document)
+ : ParentNode(document, NodeType::DOCUMENT_FRAGMENT_NODE)
+ {
+ }
+
+ virtual String tag_name() const override { return "#document-fragment"; }
+};
+
+template<>
+inline bool is<DocumentFragment>(const Node& node)
+{
+ return node.is_document_fragment();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/DocumentType.cpp b/Libraries/LibWeb/DOM/DocumentType.cpp
new file mode 100644
index 0000000000..c6481f7824
--- /dev/null
+++ b/Libraries/LibWeb/DOM/DocumentType.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/DocumentType.h>
+
+namespace Web {
+
+DocumentType::DocumentType(Document& document)
+ : Node(document, NodeType::DOCUMENT_TYPE_NODE)
+{
+}
+
+DocumentType::~DocumentType()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/DocumentType.h b/Libraries/LibWeb/DOM/DocumentType.h
new file mode 100644
index 0000000000..b863ecb98c
--- /dev/null
+++ b/Libraries/LibWeb/DOM/DocumentType.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/Node.h>
+
+namespace Web {
+
+class DocumentType final : public Node {
+public:
+ explicit DocumentType(Document&);
+ virtual ~DocumentType() override;
+
+ virtual String tag_name() const override { return "#doctype"; }
+};
+
+template<>
+inline bool is<DocumentType>(const Node& node)
+{
+ return node.type() == NodeType::DOCUMENT_TYPE_NODE;
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Element.cpp b/Libraries/LibWeb/DOM/Element.cpp
new file mode 100644
index 0000000000..fc3674a32b
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Element.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/CSS/StyleResolver.h>
+#include <LibWeb/CSS/PropertyID.h>
+#include <LibWeb/CSS/Length.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/Element.h>
+#include <LibWeb/Layout/LayoutBlock.h>
+#include <LibWeb/Layout/LayoutInline.h>
+#include <LibWeb/Layout/LayoutListItem.h>
+#include <LibWeb/Layout/LayoutTable.h>
+#include <LibWeb/Layout/LayoutTableCell.h>
+#include <LibWeb/Layout/LayoutTableRow.h>
+#include <LibWeb/Layout/LayoutTreeBuilder.h>
+
+namespace Web {
+
+Element::Element(Document& document, const String& tag_name)
+ : ParentNode(document, NodeType::ELEMENT_NODE)
+ , m_tag_name(tag_name)
+{
+}
+
+Element::~Element()
+{
+}
+
+Attribute* Element::find_attribute(const String& name)
+{
+ for (auto& attribute : m_attributes) {
+ if (attribute.name() == name)
+ return &attribute;
+ }
+ return nullptr;
+}
+
+const Attribute* Element::find_attribute(const String& name) const
+{
+ for (auto& attribute : m_attributes) {
+ if (attribute.name() == name)
+ return &attribute;
+ }
+ return nullptr;
+}
+
+String Element::attribute(const String& name) const
+{
+ if (auto* attribute = find_attribute(name))
+ return attribute->value();
+ return {};
+}
+
+void Element::set_attribute(const String& name, const String& value)
+{
+ if (auto* attribute = find_attribute(name))
+ attribute->set_value(value);
+ else
+ m_attributes.empend(name, value);
+
+ parse_attribute(name, value);
+}
+
+void Element::set_attributes(Vector<Attribute>&& attributes)
+{
+ m_attributes = move(attributes);
+
+ for (auto& attribute : m_attributes)
+ parse_attribute(attribute.name(), attribute.value());
+}
+
+bool Element::has_class(const StringView& class_name) const
+{
+ auto value = attribute("class");
+ if (value.is_empty())
+ return false;
+ auto parts = value.split_view(' ');
+ for (auto& part : parts) {
+ if (part == class_name)
+ return true;
+ }
+ return false;
+}
+
+RefPtr<LayoutNode> Element::create_layout_node(const StyleProperties* parent_style) const
+{
+ auto style = document().style_resolver().resolve_style(*this, parent_style);
+ const_cast<Element&>(*this).m_resolved_style = style;
+ auto display = style->string_or_fallback(CSS::PropertyID::Display, "inline");
+
+ if (display == "none")
+ return nullptr;
+ if (display == "block")
+ return adopt(*new LayoutBlock(this, move(style)));
+ if (display == "inline")
+ return adopt(*new LayoutInline(*this, move(style)));
+ if (display == "list-item")
+ return adopt(*new LayoutListItem(*this, move(style)));
+ if (display == "table")
+ return adopt(*new LayoutTable(*this, move(style)));
+ if (display == "table-row")
+ return adopt(*new LayoutTableRow(*this, move(style)));
+ if (display == "table-cell")
+ return adopt(*new LayoutTableCell(*this, move(style)));
+ if (display == "inline-block")
+ return adopt(*new LayoutBlock(this, move(style)));
+
+ ASSERT_NOT_REACHED();
+}
+
+void Element::parse_attribute(const String&, const String&)
+{
+}
+
+enum class StyleDifference {
+ None,
+ NeedsRepaint,
+ NeedsRelayout,
+};
+
+static StyleDifference compute_style_difference(const StyleProperties& old_style, const StyleProperties& new_style, const Document& document)
+{
+ if (old_style == new_style)
+ return StyleDifference::None;
+
+ bool needs_repaint = false;
+ bool needs_relayout = false;
+
+ if (new_style.color_or_fallback(CSS::PropertyID::Color, document, Color::Black) != old_style.color_or_fallback(CSS::PropertyID::Color, document, Color::Black))
+ needs_repaint = true;
+ else if (new_style.color_or_fallback(CSS::PropertyID::BackgroundColor, document, Color::Black) != old_style.color_or_fallback(CSS::PropertyID::BackgroundColor, document, Color::Black))
+ needs_repaint = true;
+
+ if (needs_relayout)
+ return StyleDifference::NeedsRelayout;
+ if (needs_repaint)
+ return StyleDifference::NeedsRepaint;
+ return StyleDifference::None;
+}
+
+void Element::recompute_style()
+{
+ set_needs_style_update(false);
+ ASSERT(parent());
+ auto* parent_layout_node = parent()->layout_node();
+ if (!parent_layout_node)
+ return;
+ ASSERT(parent_layout_node);
+ auto style = document().style_resolver().resolve_style(*this, &parent_layout_node->style());
+ m_resolved_style = style;
+ if (!layout_node()) {
+ if (style->string_or_fallback(CSS::PropertyID::Display, "inline") == "none")
+ return;
+ // We need a new layout tree here!
+ LayoutTreeBuilder tree_builder;
+ tree_builder.build(*this);
+ return;
+ }
+ auto diff = compute_style_difference(layout_node()->style(), *style, document());
+ if (diff == StyleDifference::None)
+ return;
+ layout_node()->set_style(*style);
+ if (diff == StyleDifference::NeedsRelayout) {
+ ASSERT_NOT_REACHED();
+ }
+ if (diff == StyleDifference::NeedsRepaint) {
+ layout_node()->set_needs_display();
+ }
+}
+
+NonnullRefPtr<StyleProperties> Element::computed_style()
+{
+ auto properties = m_resolved_style->clone();
+ if (layout_node() && layout_node()->has_style()) {
+ CSS::PropertyID box_model_metrics[] = {
+ CSS::PropertyID::MarginTop,
+ CSS::PropertyID::MarginBottom,
+ CSS::PropertyID::MarginLeft,
+ CSS::PropertyID::MarginRight,
+ CSS::PropertyID::PaddingTop,
+ CSS::PropertyID::PaddingBottom,
+ CSS::PropertyID::PaddingLeft,
+ CSS::PropertyID::PaddingRight,
+ CSS::PropertyID::BorderTopWidth,
+ CSS::PropertyID::BorderBottomWidth,
+ CSS::PropertyID::BorderLeftWidth,
+ CSS::PropertyID::BorderRightWidth,
+ };
+ for (CSS::PropertyID id : box_model_metrics) {
+ auto prop = layout_node()->style().property(id);
+ if (prop.has_value())
+ properties->set_property(id, prop.value());
+ }
+ }
+ return properties;
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Element.h b/Libraries/LibWeb/DOM/Element.h
new file mode 100644
index 0000000000..0e7af34ba8
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Element.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <LibWeb/DOM/ParentNode.h>
+#include <LibWeb/Layout/LayoutNode.h>
+
+namespace Web {
+
+class LayoutNodeWithStyle;
+
+class Attribute {
+public:
+ Attribute(const String& name, const String& value)
+ : m_name(name)
+ , m_value(value)
+ {
+ }
+
+ const String& name() const { return m_name; }
+ const String& value() const { return m_value; }
+
+ void set_value(const String& value) { m_value = value; }
+
+private:
+ String m_name;
+ String m_value;
+};
+
+class Element : public ParentNode {
+public:
+ Element(Document&, const String& tag_name);
+ virtual ~Element() override;
+
+ virtual String tag_name() const final { return m_tag_name; }
+
+ bool has_attribute(const String& name) const { return !attribute(name).is_null(); }
+ String attribute(const String& name) const;
+ void set_attribute(const String& name, const String& value);
+
+ void set_attributes(Vector<Attribute>&&);
+
+ template<typename Callback>
+ void for_each_attribute(Callback callback) const
+ {
+ for (auto& attribute : m_attributes)
+ callback(attribute.name(), attribute.value());
+ }
+
+ bool has_class(const StringView&) const;
+
+ virtual void apply_presentational_hints(StyleProperties&) const {}
+ virtual void parse_attribute(const String& name, const String& value);
+
+ void recompute_style();
+
+ LayoutNodeWithStyle* layout_node() { return static_cast<LayoutNodeWithStyle*>(Node::layout_node()); }
+ const LayoutNodeWithStyle* layout_node() const { return static_cast<const LayoutNodeWithStyle*>(Node::layout_node()); }
+
+ String name() const { return attribute("name"); }
+
+ const StyleProperties* resolved_style() const { return m_resolved_style.ptr(); }
+ NonnullRefPtr<StyleProperties> computed_style();
+
+private:
+ RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+
+ Attribute* find_attribute(const String& name);
+ const Attribute* find_attribute(const String& name) const;
+
+ String m_tag_name;
+ Vector<Attribute> m_attributes;
+
+ RefPtr<StyleProperties> m_resolved_style;
+};
+
+template<>
+inline bool is<Element>(const Node& node)
+{
+ return node.is_element();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/ElementFactory.cpp b/Libraries/LibWeb/DOM/ElementFactory.cpp
new file mode 100644
index 0000000000..b2c362fa88
--- /dev/null
+++ b/Libraries/LibWeb/DOM/ElementFactory.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/ElementFactory.h>
+#include <LibWeb/DOM/HTMLAnchorElement.h>
+#include <LibWeb/DOM/HTMLBRElement.h>
+#include <LibWeb/DOM/HTMLBlinkElement.h>
+#include <LibWeb/DOM/HTMLBodyElement.h>
+#include <LibWeb/DOM/HTMLFontElement.h>
+#include <LibWeb/DOM/HTMLFormElement.h>
+#include <LibWeb/DOM/HTMLHRElement.h>
+#include <LibWeb/DOM/HTMLHeadElement.h>
+#include <LibWeb/DOM/HTMLHeadingElement.h>
+#include <LibWeb/DOM/HTMLHtmlElement.h>
+#include <LibWeb/DOM/HTMLImageElement.h>
+#include <LibWeb/DOM/HTMLInputElement.h>
+#include <LibWeb/DOM/HTMLLinkElement.h>
+#include <LibWeb/DOM/HTMLStyleElement.h>
+#include <LibWeb/DOM/HTMLTitleElement.h>
+
+namespace Web {
+
+NonnullRefPtr<Element> create_element(Document& document, const String& tag_name)
+{
+ auto lowercase_tag_name = tag_name.to_lowercase();
+ if (lowercase_tag_name == "a")
+ return adopt(*new HTMLAnchorElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "html")
+ return adopt(*new HTMLHtmlElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "head")
+ return adopt(*new HTMLHeadElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "body")
+ return adopt(*new HTMLBodyElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "font")
+ return adopt(*new HTMLFontElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "hr")
+ return adopt(*new HTMLHRElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "style")
+ return adopt(*new HTMLStyleElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "title")
+ return adopt(*new HTMLTitleElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "link")
+ return adopt(*new HTMLLinkElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "img")
+ return adopt(*new HTMLImageElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "blink")
+ return adopt(*new HTMLBlinkElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "form")
+ return adopt(*new HTMLFormElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "input")
+ return adopt(*new HTMLInputElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "br")
+ return adopt(*new HTMLBRElement(document, lowercase_tag_name));
+ if (lowercase_tag_name == "h1"
+ || lowercase_tag_name == "h2"
+ || lowercase_tag_name == "h3"
+ || lowercase_tag_name == "h4"
+ || lowercase_tag_name == "h5"
+ || lowercase_tag_name == "h6") {
+ return adopt(*new HTMLHeadingElement(document, lowercase_tag_name));
+ }
+ return adopt(*new Element(document, lowercase_tag_name));
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/ElementFactory.h b/Libraries/LibWeb/DOM/ElementFactory.h
new file mode 100644
index 0000000000..3c494e78cd
--- /dev/null
+++ b/Libraries/LibWeb/DOM/ElementFactory.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/Element.h>
+
+namespace Web {
+
+NonnullRefPtr<Element> create_element(Document&, const String& tag_name);
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLAnchorElement.cpp b/Libraries/LibWeb/DOM/HTMLAnchorElement.cpp
new file mode 100644
index 0000000000..5fffa52fdf
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLAnchorElement.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLAnchorElement.h>
+
+namespace Web {
+
+HTMLAnchorElement::HTMLAnchorElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLAnchorElement::~HTMLAnchorElement()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLAnchorElement.h b/Libraries/LibWeb/DOM/HTMLAnchorElement.h
new file mode 100644
index 0000000000..89d20c7be4
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLAnchorElement.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLAnchorElement : public HTMLElement {
+public:
+ HTMLAnchorElement(Document&, const String& tag_name);
+ virtual ~HTMLAnchorElement() override;
+
+ String href() const { return attribute("href"); }
+};
+
+template<>
+inline bool is<HTMLAnchorElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "a";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLBRElement.cpp b/Libraries/LibWeb/DOM/HTMLBRElement.cpp
new file mode 100644
index 0000000000..f7667c44d6
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLBRElement.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLBRElement.h>
+#include <LibWeb/Layout/LayoutBreak.h>
+
+namespace Web {
+
+HTMLBRElement::HTMLBRElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLBRElement::~HTMLBRElement()
+{
+}
+
+RefPtr<LayoutNode> HTMLBRElement::create_layout_node(const StyleProperties*) const
+{
+ return adopt(*new LayoutBreak(*this));
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLBRElement.h b/Libraries/LibWeb/DOM/HTMLBRElement.h
new file mode 100644
index 0000000000..4dcf6ff185
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLBRElement.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLBRElement final : public HTMLElement {
+public:
+ HTMLBRElement(Document&, const String& tag_name);
+ virtual ~HTMLBRElement() override;
+
+ virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+};
+
+template<>
+inline bool is<HTMLBRElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "br";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLBlinkElement.cpp b/Libraries/LibWeb/DOM/HTMLBlinkElement.cpp
new file mode 100644
index 0000000000..51f8d96642
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLBlinkElement.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibCore/Timer.h>
+#include <LibWeb/CSS/StyleProperties.h>
+#include <LibWeb/CSS/StyleValue.h>
+#include <LibWeb/DOM/HTMLBlinkElement.h>
+#include <LibWeb/Layout/LayoutNode.h>
+
+namespace Web {
+
+HTMLBlinkElement::HTMLBlinkElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+ , m_timer(Core::Timer::construct())
+{
+ m_timer->set_interval(500);
+ m_timer->on_timeout = [this] { blink(); };
+ m_timer->start();
+}
+
+HTMLBlinkElement::~HTMLBlinkElement()
+{
+}
+
+void HTMLBlinkElement::blink()
+{
+ if (!layout_node())
+ return;
+
+ layout_node()->set_visible(!layout_node()->is_visible());
+ layout_node()->set_needs_display();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLBlinkElement.h b/Libraries/LibWeb/DOM/HTMLBlinkElement.h
new file mode 100644
index 0000000000..63d85b5093
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLBlinkElement.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibCore/Forward.h>
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLBlinkElement : public HTMLElement {
+public:
+ HTMLBlinkElement(Document&, const String& tag_name);
+ virtual ~HTMLBlinkElement() override;
+
+private:
+ void blink();
+
+ NonnullRefPtr<Core::Timer> m_timer;
+};
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLBodyElement.cpp b/Libraries/LibWeb/DOM/HTMLBodyElement.cpp
new file mode 100644
index 0000000000..a5fbd9dc90
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLBodyElement.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/CSS/StyleProperties.h>
+#include <LibWeb/CSS/StyleValue.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/HTMLBodyElement.h>
+
+namespace Web {
+
+HTMLBodyElement::HTMLBodyElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLBodyElement::~HTMLBodyElement()
+{
+}
+
+void HTMLBodyElement::apply_presentational_hints(StyleProperties& style) const
+{
+ for_each_attribute([&](auto& name, auto& value) {
+ if (name.equals_ignoring_case("bgcolor")) {
+ auto color = Color::from_string(value);
+ if (color.has_value())
+ style.set_property(CSS::PropertyID::BackgroundColor, ColorStyleValue::create(color.value()));
+ } else if (name.equals_ignoring_case("text")) {
+ auto color = Color::from_string(value);
+ if (color.has_value())
+ style.set_property(CSS::PropertyID::Color, ColorStyleValue::create(color.value()));
+ } else if (name.equals_ignoring_case("background")) {
+ style.set_property(CSS::PropertyID::BackgroundImage, ImageStyleValue::create(document().complete_url(value), const_cast<Document&>(document())));
+ }
+ });
+}
+
+void HTMLBodyElement::parse_attribute(const String& name, const String& value)
+{
+ if (name.equals_ignoring_case("link")) {
+ auto color = Color::from_string(value);
+ if (color.has_value())
+ document().set_link_color(color.value());
+ } else if (name.equals_ignoring_case("alink")) {
+ auto color = Color::from_string(value);
+ if (color.has_value())
+ document().set_active_link_color(color.value());
+ } else if (name.equals_ignoring_case("vlink")) {
+ auto color = Color::from_string(value);
+ if (color.has_value())
+ document().set_visited_link_color(color.value());
+ }
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLBodyElement.h b/Libraries/LibWeb/DOM/HTMLBodyElement.h
new file mode 100644
index 0000000000..22296fa46c
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLBodyElement.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLBodyElement : public HTMLElement {
+public:
+ HTMLBodyElement(Document&, const String& tag_name);
+ virtual ~HTMLBodyElement() override;
+
+ virtual void parse_attribute(const String&, const String&) override;
+ virtual void apply_presentational_hints(StyleProperties&) const override;
+};
+
+template<>
+inline bool is<HTMLBodyElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "body";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLElement.cpp b/Libraries/LibWeb/DOM/HTMLElement.cpp
new file mode 100644
index 0000000000..030a442854
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLElement.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+HTMLElement::HTMLElement(Document& document, const String& tag_name)
+ : Element(document, tag_name)
+{
+}
+
+HTMLElement::~HTMLElement()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLElement.h b/Libraries/LibWeb/DOM/HTMLElement.h
new file mode 100644
index 0000000000..56d8329b42
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLElement.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/Element.h>
+
+namespace Web {
+
+class HTMLElement : public Element {
+public:
+ HTMLElement(Document&, const String& tag_name);
+ virtual ~HTMLElement() override;
+
+ String title() const { return attribute("title"); }
+
+private:
+ virtual bool is_html_element() const final { return true; }
+};
+
+template<>
+inline bool is<HTMLElement>(const Node& node)
+{
+ return node.is_html_element();
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLFontElement.cpp b/Libraries/LibWeb/DOM/HTMLFontElement.cpp
new file mode 100644
index 0000000000..276daece4c
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLFontElement.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/CSS/StyleProperties.h>
+#include <LibWeb/CSS/StyleValue.h>
+#include <LibWeb/DOM/HTMLFontElement.h>
+
+namespace Web {
+
+HTMLFontElement::HTMLFontElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLFontElement::~HTMLFontElement()
+{
+}
+
+void HTMLFontElement::apply_presentational_hints(StyleProperties& style) const
+{
+ for_each_attribute([&](auto& name, auto& value) {
+ if (name.equals_ignoring_case("color")) {
+ auto color = Color::from_string(value);
+ if (color.has_value())
+ style.set_property(CSS::PropertyID::Color, ColorStyleValue::create(color.value()));
+ }
+ });
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLFontElement.h b/Libraries/LibWeb/DOM/HTMLFontElement.h
new file mode 100644
index 0000000000..57d0088426
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLFontElement.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLFontElement : public HTMLElement {
+public:
+ HTMLFontElement(Document&, const String& tag_name);
+ virtual ~HTMLFontElement() override;
+
+ virtual void apply_presentational_hints(StyleProperties&) const override;
+};
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLFormElement.cpp b/Libraries/LibWeb/DOM/HTMLFormElement.cpp
new file mode 100644
index 0000000000..f7092a73d0
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLFormElement.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/StringBuilder.h>
+#include <LibWeb/DOM/HTMLFormElement.h>
+#include <LibWeb/DOM/HTMLInputElement.h>
+#include <LibWeb/Frame.h>
+#include <LibWeb/HtmlView.h>
+
+namespace Web {
+
+HTMLFormElement::HTMLFormElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLFormElement::~HTMLFormElement()
+{
+}
+
+void HTMLFormElement::submit()
+{
+ if (action().is_null()) {
+ dbg() << "Unsupported form action ''";
+ return;
+ }
+
+ if (method().to_lowercase() != "get") {
+ dbg() << "Unsupported form method '" << method() << "'";
+ return;
+ }
+
+ URL url(document().complete_url(action()));
+
+ struct NameAndValue {
+ String name;
+ String value;
+ };
+
+ Vector<NameAndValue> parameters;
+
+ for_each_in_subtree_of_type<HTMLInputElement>([&](auto& node) {
+ auto& input = to<HTMLInputElement>(node);
+ if (!input.name().is_null())
+ parameters.append({ input.name(), input.value() });
+ return IterationDecision::Continue;
+ });
+
+ StringBuilder builder;
+ for (size_t i = 0; i < parameters.size(); ++i) {
+ builder.append(parameters[i].name);
+ builder.append('=');
+ builder.append(parameters[i].value);
+ if (i != parameters.size() - 1)
+ builder.append('&');
+ }
+ url.set_query(builder.to_string());
+
+ // FIXME: We shouldn't let the form just do this willy-nilly.
+ document().frame()->html_view()->load(url);
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLFormElement.h b/Libraries/LibWeb/DOM/HTMLFormElement.h
new file mode 100644
index 0000000000..bd99ce5c07
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLFormElement.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLFormElement : public HTMLElement {
+public:
+ HTMLFormElement(Document&, const String& tag_name);
+ virtual ~HTMLFormElement() override;
+
+ String action() const { return attribute("action"); }
+ String method() const { return attribute("method"); }
+
+ void submit();
+};
+
+template<>
+inline bool is<HTMLFormElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "form";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHRElement.cpp b/Libraries/LibWeb/DOM/HTMLHRElement.cpp
new file mode 100644
index 0000000000..7d4dbb4a3b
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHRElement.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLHRElement.h>
+
+namespace Web {
+
+HTMLHRElement::HTMLHRElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLHRElement::~HTMLHRElement()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHRElement.h b/Libraries/LibWeb/DOM/HTMLHRElement.h
new file mode 100644
index 0000000000..48a57026f9
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHRElement.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLHRElement : public HTMLElement {
+public:
+ HTMLHRElement(Document&, const String& tag_name);
+ virtual ~HTMLHRElement() override;
+};
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHeadElement.cpp b/Libraries/LibWeb/DOM/HTMLHeadElement.cpp
new file mode 100644
index 0000000000..6d828b269e
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHeadElement.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLHeadElement.h>
+
+namespace Web {
+
+HTMLHeadElement::HTMLHeadElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLHeadElement::~HTMLHeadElement()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHeadElement.h b/Libraries/LibWeb/DOM/HTMLHeadElement.h
new file mode 100644
index 0000000000..5acb84ea91
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHeadElement.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLHeadElement : public HTMLElement {
+public:
+ HTMLHeadElement(Document&, const String& tag_name);
+ virtual ~HTMLHeadElement() override;
+};
+
+template<>
+inline bool is<HTMLHeadElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "head";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHeadingElement.cpp b/Libraries/LibWeb/DOM/HTMLHeadingElement.cpp
new file mode 100644
index 0000000000..fab61fda51
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHeadingElement.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLHeadingElement.h>
+
+namespace Web {
+
+HTMLHeadingElement::HTMLHeadingElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLHeadingElement::~HTMLHeadingElement()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHeadingElement.h b/Libraries/LibWeb/DOM/HTMLHeadingElement.h
new file mode 100644
index 0000000000..0a8ad9ec4f
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHeadingElement.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLHeadingElement : public HTMLElement {
+public:
+ HTMLHeadingElement(Document&, const String& tag_name);
+ virtual ~HTMLHeadingElement() override;
+};
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHtmlElement.cpp b/Libraries/LibWeb/DOM/HTMLHtmlElement.cpp
new file mode 100644
index 0000000000..af1355cbde
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHtmlElement.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLHtmlElement.h>
+
+namespace Web {
+
+HTMLHtmlElement::HTMLHtmlElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLHtmlElement::~HTMLHtmlElement()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLHtmlElement.h b/Libraries/LibWeb/DOM/HTMLHtmlElement.h
new file mode 100644
index 0000000000..d926c3459d
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLHtmlElement.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLHtmlElement : public HTMLElement {
+public:
+ HTMLHtmlElement(Document&, const String& tag_name);
+ virtual ~HTMLHtmlElement() override;
+};
+
+template<>
+inline bool is<HTMLHtmlElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "html";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLImageElement.cpp b/Libraries/LibWeb/DOM/HTMLImageElement.cpp
new file mode 100644
index 0000000000..f1db4428f9
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLImageElement.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibGfx/Bitmap.h>
+#include <LibGfx/ImageDecoder.h>
+#include <LibWeb/CSS/StyleResolver.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/HTMLImageElement.h>
+#include <LibWeb/Layout/LayoutImage.h>
+#include <LibWeb/ResourceLoader.h>
+
+namespace Web {
+
+HTMLImageElement::HTMLImageElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLImageElement::~HTMLImageElement()
+{
+}
+
+void HTMLImageElement::parse_attribute(const String& name, const String& value)
+{
+ if (name.equals_ignoring_case("src"))
+ load_image(value);
+}
+
+void HTMLImageElement::load_image(const String& src)
+{
+ URL src_url = document().complete_url(src);
+ ResourceLoader::the().load(src_url, [this, weak_element = make_weak_ptr()](auto data) {
+ if (!weak_element) {
+ dbg() << "HTMLImageElement: Load completed after element destroyed.";
+ return;
+ }
+ if (data.is_null()) {
+ dbg() << "HTMLImageElement: Failed to load " << this->src();
+ return;
+ }
+
+ m_encoded_data = data;
+ m_image_decoder = Gfx::ImageDecoder::create(m_encoded_data.data(), m_encoded_data.size());
+ document().update_layout();
+ });
+}
+
+int HTMLImageElement::preferred_width() const
+{
+ bool ok = false;
+ int width = attribute("width").to_int(ok);
+ if (ok)
+ return width;
+
+ if (m_image_decoder)
+ return m_image_decoder->width();
+
+ return 0;
+}
+
+int HTMLImageElement::preferred_height() const
+{
+ bool ok = false;
+ int height = attribute("height").to_int(ok);
+ if (ok)
+ return height;
+
+ if (m_image_decoder)
+ return m_image_decoder->height();
+
+ return 0;
+}
+
+RefPtr<LayoutNode> HTMLImageElement::create_layout_node(const StyleProperties* parent_style) const
+{
+ auto style = document().style_resolver().resolve_style(*this, parent_style);
+ auto display = style->string_or_fallback(CSS::PropertyID::Display, "inline");
+ if (display == "none")
+ return nullptr;
+ return adopt(*new LayoutImage(*this, move(style)));
+}
+
+const Gfx::Bitmap* HTMLImageElement::bitmap() const
+{
+ if (!m_image_decoder)
+ return nullptr;
+ return m_image_decoder->bitmap();
+}
+
+void HTMLImageElement::set_volatile(Badge<LayoutDocument>, bool v)
+{
+ if (!m_image_decoder)
+ return;
+ if (v) {
+ m_image_decoder->set_volatile();
+ return;
+ }
+ bool has_image = m_image_decoder->set_nonvolatile();
+ if (has_image)
+ return;
+ m_image_decoder = Gfx::ImageDecoder::create(m_encoded_data.data(), m_encoded_data.size());
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLImageElement.h b/Libraries/LibWeb/DOM/HTMLImageElement.h
new file mode 100644
index 0000000000..f30f37d3a1
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLImageElement.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/ByteBuffer.h>
+#include <LibGfx/Forward.h>
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class LayoutDocument;
+
+class HTMLImageElement : public HTMLElement {
+public:
+ HTMLImageElement(Document&, const String& tag_name);
+ virtual ~HTMLImageElement() override;
+
+ virtual void parse_attribute(const String& name, const String& value) override;
+
+ String alt() const { return attribute("alt"); }
+ String src() const { return attribute("src"); }
+ int preferred_width() const;
+ int preferred_height() const;
+
+ const Gfx::Bitmap* bitmap() const;
+ const Gfx::ImageDecoder* image_decoder() const { return m_image_decoder; }
+
+ void set_volatile(Badge<LayoutDocument>, bool);
+
+private:
+ void load_image(const String& src);
+
+ virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+
+ RefPtr<Gfx::ImageDecoder> m_image_decoder;
+ ByteBuffer m_encoded_data;
+};
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLInputElement.cpp b/Libraries/LibWeb/DOM/HTMLInputElement.cpp
new file mode 100644
index 0000000000..bd7194f251
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLInputElement.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibCore/ElapsedTimer.h>
+#include <LibGUI/Button.h>
+#include <LibGUI/TextBox.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/HTMLFormElement.h>
+#include <LibWeb/DOM/HTMLInputElement.h>
+#include <LibWeb/Frame.h>
+#include <LibWeb/HtmlView.h>
+#include <LibWeb/Layout/LayoutWidget.h>
+
+namespace Web {
+
+HTMLInputElement::HTMLInputElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLInputElement::~HTMLInputElement()
+{
+}
+
+RefPtr<LayoutNode> HTMLInputElement::create_layout_node(const StyleProperties*) const
+{
+ ASSERT(document().frame());
+ auto& frame = *document().frame();
+ ASSERT(frame.html_view());
+ auto& html_view = const_cast<HtmlView&>(*frame.html_view());
+
+ RefPtr<GUI::Widget> widget;
+ if (type() == "submit") {
+ auto& button = html_view.add<GUI::Button>(value());
+ int text_width = Gfx::Font::default_font().width(value());
+ button.set_relative_rect(0, 0, text_width + 20, 20);
+ button.on_click = [this] {
+ if (auto* form = first_ancestor_of_type<HTMLFormElement>()) {
+ // FIXME: Remove this const_cast once we have a non-const first_ancestor_of_type.
+ const_cast<HTMLFormElement*>(form)->submit();
+ }
+ };
+ widget = button;
+ } else {
+ auto& text_box = html_view.add<GUI::TextBox>();
+ text_box.set_text(value());
+ text_box.on_change = [this] {
+ auto& widget = to<LayoutWidget>(layout_node())->widget();
+ const_cast<HTMLInputElement*>(this)->set_attribute("value", static_cast<const GUI::TextBox&>(widget).text());
+ };
+ int text_width = Gfx::Font::default_font().width(value());
+ text_box.set_relative_rect(0, 0, text_width + 20, 20);
+ widget = text_box;
+ }
+
+ return adopt(*new LayoutWidget(*this, *widget));
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLInputElement.h b/Libraries/LibWeb/DOM/HTMLInputElement.h
new file mode 100644
index 0000000000..f54d6efa6b
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLInputElement.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLInputElement : public HTMLElement {
+public:
+ HTMLInputElement(Document&, const String& tag_name);
+ virtual ~HTMLInputElement() override;
+
+ virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+
+ String type() const { return attribute("type"); }
+ String value() const { return attribute("value"); }
+ String name() const { return attribute("name"); }
+};
+
+template<>
+inline bool is<HTMLInputElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "input";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLLinkElement.cpp b/Libraries/LibWeb/DOM/HTMLLinkElement.cpp
new file mode 100644
index 0000000000..f2bd9e8aed
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLLinkElement.cpp
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/ByteBuffer.h>
+#include <AK/URL.h>
+#include <LibCore/File.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/HTMLLinkElement.h>
+#include <LibWeb/Parser/CSSParser.h>
+#include <LibWeb/ResourceLoader.h>
+
+namespace Web {
+
+HTMLLinkElement::HTMLLinkElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLLinkElement::~HTMLLinkElement()
+{
+}
+
+void HTMLLinkElement::inserted_into(Node&)
+{
+ if (rel() == "stylesheet") {
+ URL url = document().complete_url(href());
+ ResourceLoader::the().load(url, [&](auto data) {
+ if (data.is_null()) {
+ dbg() << "HTMLLinkElement: Failed to load stylesheet: " << href();
+ return;
+ }
+ auto sheet = parse_css(data);
+ if (!sheet) {
+ dbg() << "HTMLLinkElement: Failed to parse stylesheet: " << href();
+ return;
+ }
+ document().add_sheet(*sheet);
+ document().update_style();
+ });
+ }
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLLinkElement.h b/Libraries/LibWeb/DOM/HTMLLinkElement.h
new file mode 100644
index 0000000000..ad005b4e93
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLLinkElement.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLLinkElement final : public HTMLElement {
+public:
+ HTMLLinkElement(Document&, const String& tag_name);
+ virtual ~HTMLLinkElement() override;
+
+ virtual void inserted_into(Node&) override;
+
+ String rel() const { return attribute("rel"); }
+ String type() const { return attribute("type"); }
+ String href() const { return attribute("href"); }
+};
+
+template<>
+inline bool is<HTMLLinkElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "link";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLStyleElement.cpp b/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
new file mode 100644
index 0000000000..4a48fb3fa1
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLStyleElement.cpp
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/StringBuilder.h>
+#include <LibWeb/DOM/Document.h>
+#include <LibWeb/DOM/HTMLStyleElement.h>
+#include <LibWeb/DOM/Text.h>
+#include <LibWeb/Parser/CSSParser.h>
+
+namespace Web {
+
+HTMLStyleElement::HTMLStyleElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLStyleElement::~HTMLStyleElement()
+{
+}
+
+void HTMLStyleElement::inserted_into(Node& new_parent)
+{
+ StringBuilder builder;
+ for_each_child([&](auto& child) {
+ if (is<Text>(child))
+ builder.append(to<Text>(child).text_content());
+ });
+ m_stylesheet = parse_css(builder.to_string());
+ if (m_stylesheet)
+ document().add_sheet(*m_stylesheet);
+ HTMLElement::inserted_into(new_parent);
+}
+
+void HTMLStyleElement::removed_from(Node& old_parent)
+{
+ if (m_stylesheet) {
+ // FIXME: Remove the sheet from the document
+ }
+ return HTMLElement::removed_from(old_parent);
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLStyleElement.h b/Libraries/LibWeb/DOM/HTMLStyleElement.h
new file mode 100644
index 0000000000..f4534c9dab
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLStyleElement.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class StyleSheet;
+
+class HTMLStyleElement : public HTMLElement {
+public:
+ HTMLStyleElement(Document&, const String& tag_name);
+ virtual ~HTMLStyleElement() override;
+
+ virtual void inserted_into(Node&) override;
+ virtual void removed_from(Node&) override;
+
+private:
+ RefPtr<StyleSheet> m_stylesheet;
+};
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLTitleElement.cpp b/Libraries/LibWeb/DOM/HTMLTitleElement.cpp
new file mode 100644
index 0000000000..c523c8812e
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLTitleElement.cpp
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/HTMLTitleElement.h>
+
+namespace Web {
+
+HTMLTitleElement::HTMLTitleElement(Document& document, const String& tag_name)
+ : HTMLElement(document, tag_name)
+{
+}
+
+HTMLTitleElement::~HTMLTitleElement()
+{
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/HTMLTitleElement.h b/Libraries/LibWeb/DOM/HTMLTitleElement.h
new file mode 100644
index 0000000000..6485a3d428
--- /dev/null
+++ b/Libraries/LibWeb/DOM/HTMLTitleElement.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/HTMLElement.h>
+
+namespace Web {
+
+class HTMLTitleElement : public HTMLElement {
+public:
+ HTMLTitleElement(Document&, const String& tag_name);
+ virtual ~HTMLTitleElement() override;
+};
+
+template<>
+inline bool is<HTMLTitleElement>(const Node& node)
+{
+ return is<Element>(node) && to<Element>(node).tag_name().to_lowercase() == "title";
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Node.cpp b/Libraries/LibWeb/DOM/Node.cpp
new file mode 100644
index 0000000000..7c2341b0cb
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Node.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <AK/StringBuilder.h>
+#include <LibWeb/CSS/StyleResolver.h>
+#include <LibWeb/DOM/Element.h>
+#include <LibWeb/DOM/HTMLAnchorElement.h>
+#include <LibWeb/DOM/Node.h>
+#include <LibWeb/Layout/LayoutBlock.h>
+#include <LibWeb/Layout/LayoutDocument.h>
+#include <LibWeb/Layout/LayoutInline.h>
+#include <LibWeb/Layout/LayoutNode.h>
+#include <LibWeb/Layout/LayoutText.h>
+
+namespace Web {
+
+Node::Node(Document& document, NodeType type)
+ : m_document(document)
+ , m_type(type)
+{
+}
+
+Node::~Node()
+{
+}
+
+const HTMLAnchorElement* Node::enclosing_link_element() const
+{
+ for (auto* node = this; node; node = node->parent()) {
+ if (is<HTMLAnchorElement>(*node) && to<HTMLAnchorElement>(*node).has_attribute("href"))
+ return to<HTMLAnchorElement>(node);
+ }
+ return nullptr;
+}
+
+const HTMLElement* Node::enclosing_html_element() const
+{
+ return first_ancestor_of_type<HTMLElement>();
+}
+
+String Node::text_content() const
+{
+ Vector<String> strings;
+ StringBuilder builder;
+ for (auto* child = first_child(); child; child = child->next_sibling()) {
+ auto text = child->text_content();
+ if (!text.is_empty()) {
+ builder.append(child->text_content());
+ builder.append(' ');
+ }
+ }
+ if (builder.length() > 1)
+ builder.trim(1);
+ return builder.to_string();
+}
+
+const Element* Node::next_element_sibling() const
+{
+ for (auto* node = next_sibling(); node; node = node->next_sibling()) {
+ if (node->is_element())
+ return static_cast<const Element*>(node);
+ }
+ return nullptr;
+}
+
+const Element* Node::previous_element_sibling() const
+{
+ for (auto* node = previous_sibling(); node; node = node->previous_sibling()) {
+ if (node->is_element())
+ return static_cast<const Element*>(node);
+ }
+ return nullptr;
+}
+
+RefPtr<LayoutNode> Node::create_layout_node(const StyleProperties*) const
+{
+ return nullptr;
+}
+
+void Node::invalidate_style()
+{
+ for_each_in_subtree_of_type<Element>([&](auto& element) {
+ element.set_needs_style_update(true);
+ return IterationDecision::Continue;
+ });
+ document().schedule_style_update();
+}
+
+bool Node::is_link() const
+{
+ auto* enclosing_link = enclosing_link_element();
+ if (!enclosing_link)
+ return false;
+ return enclosing_link->has_attribute("href");
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Node.h b/Libraries/LibWeb/DOM/Node.h
new file mode 100644
index 0000000000..51a48bdffd
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Node.h
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/Badge.h>
+#include <AK/RefPtr.h>
+#include <AK/String.h>
+#include <AK/Vector.h>
+#include <LibWeb/TreeNode.h>
+
+namespace Web {
+
+enum class NodeType : unsigned {
+ INVALID = 0,
+ ELEMENT_NODE = 1,
+ TEXT_NODE = 3,
+ COMMENT_NODE = 8,
+ DOCUMENT_NODE = 9,
+ DOCUMENT_TYPE_NODE = 10,
+ DOCUMENT_FRAGMENT_NODE = 11,
+};
+
+class Document;
+class Element;
+class HTMLElement;
+class HTMLAnchorElement;
+class ParentNode;
+class LayoutNode;
+class StyleResolver;
+class StyleProperties;
+
+class Node : public TreeNode<Node> {
+public:
+ virtual ~Node();
+
+ NodeType type() const { return m_type; }
+ bool is_element() const { return type() == NodeType::ELEMENT_NODE; }
+ bool is_text() const { return type() == NodeType::TEXT_NODE; }
+ bool is_document() const { return type() == NodeType::DOCUMENT_NODE; }
+ bool is_document_type() const { return type() == NodeType::DOCUMENT_TYPE_NODE; }
+ bool is_comment() const { return type() == NodeType::COMMENT_NODE; }
+ bool is_character_data() const { return type() == NodeType::TEXT_NODE || type() == NodeType::COMMENT_NODE; }
+ bool is_document_fragment() const { return type() == NodeType::DOCUMENT_FRAGMENT_NODE; }
+ bool is_parent_node() const { return is_element() || is_document(); }
+
+ virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const;
+
+ virtual String tag_name() const = 0;
+
+ virtual String text_content() const;
+
+ Document& document() { return m_document; }
+ const Document& document() const { return m_document; }
+
+ const HTMLAnchorElement* enclosing_link_element() const;
+ const HTMLElement* enclosing_html_element() const;
+
+ virtual bool is_html_element() const { return false; }
+
+ template<typename T>
+ const T* first_child_of_type() const;
+
+ template<typename T>
+ const T* first_ancestor_of_type() const;
+
+ virtual void inserted_into(Node&) {}
+ virtual void removed_from(Node&) {}
+
+ const LayoutNode* layout_node() const { return m_layout_node; }
+ LayoutNode* layout_node() { return m_layout_node; }
+
+ void set_layout_node(Badge<LayoutNode>, LayoutNode* layout_node) const { m_layout_node = layout_node; }
+
+ const Element* previous_element_sibling() const;
+ const Element* next_element_sibling() const;
+
+ virtual bool is_child_allowed(const Node&) const { return true; }
+
+ bool needs_style_update() const { return m_needs_style_update; }
+ void set_needs_style_update(bool value) { m_needs_style_update = value; }
+
+ void invalidate_style();
+
+ bool is_link() const;
+
+protected:
+ Node(Document&, NodeType);
+
+ Document& m_document;
+ mutable LayoutNode* m_layout_node { nullptr };
+ NodeType m_type { NodeType::INVALID };
+ bool m_needs_style_update { false };
+};
+
+template<typename T>
+inline bool is(const Node&)
+{
+ return false;
+}
+
+template<typename T>
+inline bool is(const Node* node)
+{
+ return !node || is<T>(*node);
+}
+
+template<>
+inline bool is<Node>(const Node&)
+{
+ return true;
+}
+
+template<>
+inline bool is<ParentNode>(const Node& node)
+{
+ return node.is_parent_node();
+}
+
+template<typename T>
+inline const T& to(const Node& node)
+{
+ ASSERT(is<T>(node));
+ return static_cast<const T&>(node);
+}
+
+template<typename T>
+inline T* to(Node* node)
+{
+ ASSERT(is<T>(node));
+ return static_cast<T*>(node);
+}
+
+template<typename T>
+inline const T* to(const Node* node)
+{
+ ASSERT(is<T>(node));
+ return static_cast<const T*>(node);
+}
+
+template<typename T>
+inline T& to(Node& node)
+{
+ ASSERT(is<T>(node));
+ return static_cast<T&>(node);
+}
+
+template<typename T>
+inline const T* Node::first_child_of_type() const
+{
+ for (auto* child = first_child(); child; child = child->next_sibling()) {
+ if (is<T>(*child))
+ return to<T>(child);
+ }
+ return nullptr;
+}
+
+template<typename T>
+inline const T* Node::first_ancestor_of_type() const
+{
+ for (auto* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+ if (is<T>(*ancestor))
+ return to<T>(ancestor);
+ }
+ return nullptr;
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/ParentNode.cpp b/Libraries/LibWeb/DOM/ParentNode.cpp
new file mode 100644
index 0000000000..3bc86e480d
--- /dev/null
+++ b/Libraries/LibWeb/DOM/ParentNode.cpp
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/ParentNode.h>
+
diff --git a/Libraries/LibWeb/DOM/ParentNode.h b/Libraries/LibWeb/DOM/ParentNode.h
new file mode 100644
index 0000000000..e8e826c959
--- /dev/null
+++ b/Libraries/LibWeb/DOM/ParentNode.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <LibWeb/DOM/Node.h>
+
+namespace Web {
+
+class ParentNode : public Node {
+public:
+ template<typename F> void for_each_child(F) const;
+ template<typename F> void for_each_child(F);
+
+protected:
+ explicit ParentNode(Document& document, NodeType type)
+ : Node(document, type)
+ {
+ }
+};
+
+template<typename Callback>
+inline void ParentNode::for_each_child(Callback callback) const
+{
+ for (auto* node = first_child(); node; node = node->next_sibling())
+ callback(*node);
+}
+
+template<typename Callback>
+inline void ParentNode::for_each_child(Callback callback)
+{
+ for (auto* node = first_child(); node; node = node->next_sibling())
+ callback(*node);
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Text.cpp b/Libraries/LibWeb/DOM/Text.cpp
new file mode 100644
index 0000000000..65c2e36550
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Text.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <LibWeb/DOM/Text.h>
+#include <LibWeb/Layout/LayoutText.h>
+
+namespace Web {
+
+Text::Text(Document& document, const String& data)
+ : CharacterData(document, NodeType::TEXT_NODE, data)
+{
+}
+
+Text::~Text()
+{
+}
+
+RefPtr<LayoutNode> Text::create_layout_node(const StyleProperties*) const
+{
+ return adopt(*new LayoutText(*this));
+}
+
+}
diff --git a/Libraries/LibWeb/DOM/Text.h b/Libraries/LibWeb/DOM/Text.h
new file mode 100644
index 0000000000..5a482ed6a0
--- /dev/null
+++ b/Libraries/LibWeb/DOM/Text.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <AK/String.h>
+#include <LibWeb/DOM/CharacterData.h>
+
+namespace Web {
+
+class Text final : public CharacterData {
+public:
+ explicit Text(Document&, const String&);
+ virtual ~Text() override;
+
+ virtual String tag_name() const override { return "#text"; }
+
+private:
+ virtual RefPtr<LayoutNode> create_layout_node(const StyleProperties* parent_style) const override;
+};
+
+template<>
+inline bool is<Text>(const Node& node)
+{
+ return node.is_text();
+}
+
+}