diff --git a/Libraries/LibWeb/DOM/Document.h b/Libraries/LibWeb/DOM/Document.h index 03ed3108b0..8f58a97353 100644 --- a/Libraries/LibWeb/DOM/Document.h +++ b/Libraries/LibWeb/DOM/Document.h @@ -167,6 +167,13 @@ public: void set_focused_element(Element*); + bool created_for_appropriate_template_contents() const { return m_created_for_appropriate_template_contents; } + void set_created_for_appropriate_template_contents(bool value) { m_created_for_appropriate_template_contents = value; } + + Document* associated_inert_template_document() { return m_associated_inert_template_document; } + const Document* associated_inert_template_document() const { return m_associated_inert_template_document; } + void set_associated_inert_template_document(Document& document) { m_associated_inert_template_document = document; } + private: virtual RefPtr create_layout_node(const CSS::StyleProperties* parent_style) override; @@ -199,6 +206,9 @@ private: bool m_editable { false }; WeakPtr m_focused_element; + + bool m_created_for_appropriate_template_contents { false }; + RefPtr m_associated_inert_template_document; }; } diff --git a/Libraries/LibWeb/DOM/DocumentFragment.h b/Libraries/LibWeb/DOM/DocumentFragment.h index b969fbde4a..b067b7e429 100644 --- a/Libraries/LibWeb/DOM/DocumentFragment.h +++ b/Libraries/LibWeb/DOM/DocumentFragment.h @@ -29,6 +29,7 @@ #include #include #include +#include namespace Web::DOM { @@ -36,10 +37,20 @@ class DocumentFragment : public ParentNode , public NonElementParentNode { public: - DocumentFragment(Document& document); + using WrapperType = Bindings::DocumentFragmentWrapper; + + explicit DocumentFragment(Document& document); virtual ~DocumentFragment() override; virtual FlyString node_name() const override { return "#document-fragment"; } + + Element& host() { return *m_host; } + const Element& host() const { return *m_host; } + + void set_host(Element& host) { m_host = host; } + +private: + RefPtr m_host; }; } diff --git a/Libraries/LibWeb/DOMTreeModel.cpp b/Libraries/LibWeb/DOMTreeModel.cpp index a8c30e2f23..c8c6a43ce2 100644 --- a/Libraries/LibWeb/DOMTreeModel.cpp +++ b/Libraries/LibWeb/DOMTreeModel.cpp @@ -63,6 +63,8 @@ GUI::ModelIndex DOMTreeModel::parent_index(const GUI::ModelIndex& index) const if (!node.parent()) return {}; + // FIXME: Handle the template element (child elements are not stored in it, all of its children are in its document fragment "content") + // No grandparent? Parent is the document! if (!node.parent()->parent()) { return create_index(0, 0, m_document.ptr()); diff --git a/Libraries/LibWeb/Dump.cpp b/Libraries/LibWeb/Dump.cpp index f6475f8bd4..002e71795b 100644 --- a/Libraries/LibWeb/Dump.cpp +++ b/Libraries/LibWeb/Dump.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include #include @@ -67,9 +68,14 @@ void dump_tree(const DOM::Node& node) } ++indent; if (is(node)) { - static_cast(node).for_each_child([](auto& child) { - dump_tree(child); - }); + if (!is(node)) { + static_cast(node).for_each_child([](auto& child) { + dump_tree(child); + }); + } else { + auto& template_element = downcast(node); + dump_tree(template_element.content()); + } } --indent; } diff --git a/Libraries/LibWeb/Forward.h b/Libraries/LibWeb/Forward.h index f553a823d6..c162796c22 100644 --- a/Libraries/LibWeb/Forward.h +++ b/Libraries/LibWeb/Forward.h @@ -159,6 +159,7 @@ namespace Web::Bindings { class CanvasRenderingContext2DWrapper; class CharacterDataWrapper; class CommentWrapper; +class DocumentFragmentWrapper; class DocumentTypeWrapper; class DocumentWrapper; class ElementWrapper; diff --git a/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp b/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp index aeb8679a40..8a3b0812e0 100644 --- a/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLTemplateElement.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include #include namespace Web::HTML { @@ -31,10 +32,30 @@ namespace Web::HTML { HTMLTemplateElement::HTMLTemplateElement(DOM::Document& document, const FlyString& tag_name) : HTMLElement(document, tag_name) { + m_content = adopt(*new DOM::DocumentFragment(appropriate_template_contents_owner_document(document))); + m_content->set_host(*this); } HTMLTemplateElement::~HTMLTemplateElement() { } +DOM::Document& HTMLTemplateElement::appropriate_template_contents_owner_document(DOM::Document& document) +{ + if (!document.created_for_appropriate_template_contents()) { + if (!document.associated_inert_template_document()) { + DOM::Document new_document; + new_document.set_created_for_appropriate_template_contents(true); + + // FIXME: If doc is an HTML document, mark new doc as an HTML document also. + + document.set_associated_inert_template_document(new_document); + } + + return *document.associated_inert_template_document(); + } + + return document; +} + } diff --git a/Libraries/LibWeb/HTML/HTMLTemplateElement.h b/Libraries/LibWeb/HTML/HTMLTemplateElement.h index 9a8ceda156..47e383cf74 100644 --- a/Libraries/LibWeb/HTML/HTMLTemplateElement.h +++ b/Libraries/LibWeb/HTML/HTMLTemplateElement.h @@ -26,6 +26,7 @@ #pragma once +#include #include namespace Web::HTML { @@ -36,6 +37,14 @@ public: HTMLTemplateElement(DOM::Document&, const FlyString& local_name); virtual ~HTMLTemplateElement() override; + + NonnullRefPtr content() { return *m_content; } + const NonnullRefPtr content() const { return *m_content; } + +private: + DOM::Document& appropriate_template_contents_owner_document(DOM::Document&); + + RefPtr m_content; }; } diff --git a/Libraries/LibWeb/HTML/HTMLTemplateElement.idl b/Libraries/LibWeb/HTML/HTMLTemplateElement.idl index 2302740878..b5d2d69511 100644 --- a/Libraries/LibWeb/HTML/HTMLTemplateElement.idl +++ b/Libraries/LibWeb/HTML/HTMLTemplateElement.idl @@ -1,5 +1,5 @@ interface HTMLTemplateElement : HTMLElement { - + readonly attribute DocumentFragment content; } diff --git a/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp b/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp index ca8ab1f683..62772ce7f8 100644 --- a/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp +++ b/Libraries/LibWeb/HTML/Parser/HTMLDocumentParser.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -385,18 +386,33 @@ DOM::Element& HTMLDocumentParser::node_before_current_node() HTMLDocumentParser::AdjustedInsertionLocation HTMLDocumentParser::find_appropriate_place_for_inserting_node() { auto& target = current_node(); + HTMLDocumentParser::AdjustedInsertionLocation adjusted_insertion_location; + if (m_foster_parenting && target.local_name().is_one_of(HTML::TagNames::table, HTML::TagNames::tbody, HTML::TagNames::tfoot, HTML::TagNames::thead, HTML::TagNames::tr)) { - // FIXME: There's a bunch of steps for