diff options
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/CharacterData.h | 2 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Node.cpp | 41 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Node.h | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/DOM/Node.idl | 6 |
4 files changed, 40 insertions, 14 deletions
diff --git a/Userland/Libraries/LibWeb/DOM/CharacterData.h b/Userland/Libraries/LibWeb/DOM/CharacterData.h index 600566d8bd..f80ff1ad8a 100644 --- a/Userland/Libraries/LibWeb/DOM/CharacterData.h +++ b/Userland/Libraries/LibWeb/DOM/CharacterData.h @@ -25,8 +25,6 @@ public: unsigned length() const { return m_data.length(); } - virtual String text_content() const override { return m_data; } - protected: explicit CharacterData(Document&, NodeType, const String&); diff --git a/Userland/Libraries/LibWeb/DOM/Node.cpp b/Userland/Libraries/LibWeb/DOM/Node.cpp index 520da6d8d1..c78dc61ab5 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.cpp +++ b/Userland/Libraries/LibWeb/DOM/Node.cpp @@ -98,22 +98,45 @@ const HTML::HTMLElement* Node::enclosing_html_element_with_attribute(const FlySt return nullptr; } -String Node::text_content() const +// https://dom.spec.whatwg.org/#concept-descendant-text-content +String Node::descendant_text_content() const { StringBuilder builder; - for (auto* child = first_child(); child; child = child->next_sibling()) { - builder.append(child->text_content()); - } + for_each_in_subtree_of_type<Text>([&](auto& text_node) { + builder.append(text_node.data()); + return IterationDecision::Continue; + }); return builder.to_string(); } -void Node::set_text_content(const String& content) +// https://dom.spec.whatwg.org/#dom-node-textcontent +String Node::text_content() const +{ + if (is<DocumentFragment>(this) || is<Element>(this)) + return descendant_text_content(); + else if (is<CharacterData>(this)) + return verify_cast<CharacterData>(this)->data(); + + // FIXME: Else if this is an Attr node, return this's value. + + return {}; +} + +// https://dom.spec.whatwg.org/#ref-for-dom-node-textcontent%E2%91%A0 +void Node::set_text_content(String const& content) { - if (is_text()) { - verify_cast<Text>(this)->set_data(content); + if (is<DocumentFragment>(this) || is<Element>(this)) { + string_replace_all(content); + } else if (is<CharacterData>(this)) { + // FIXME: CharacterData::set_data is not spec compliant. Make this match the spec when set_data becomes spec compliant. + // Do note that this will make this function able to throw an exception. + + auto* character_data_node = verify_cast<CharacterData>(this); + character_data_node->set_data(content); } else { - remove_all_children(); - append_child(document().create_text_node(content)); + // FIXME: Else if this is an Attr node, set an existing attribute value with this and the given value. + + return; } set_needs_style_update(true); diff --git a/Userland/Libraries/LibWeb/DOM/Node.h b/Userland/Libraries/LibWeb/DOM/Node.h index 22cca3cb00..9287a97430 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.h +++ b/Userland/Libraries/LibWeb/DOM/Node.h @@ -99,8 +99,9 @@ public: virtual FlyString node_name() const = 0; - virtual String text_content() const; - void set_text_content(const String&); + String descendant_text_content() const; + String text_content() const; + void set_text_content(String const&); Document& document() { return *m_document; } const Document& document() const { return *m_document; } diff --git a/Userland/Libraries/LibWeb/DOM/Node.idl b/Userland/Libraries/LibWeb/DOM/Node.idl index edd50ca84f..603095e5ed 100644 --- a/Userland/Libraries/LibWeb/DOM/Node.idl +++ b/Userland/Libraries/LibWeb/DOM/Node.idl @@ -14,7 +14,11 @@ interface Node : EventTarget { readonly attribute Element? parentElement; readonly attribute boolean isConnected; readonly attribute Document? ownerDocument; - attribute DOMString textContent; + + // FIXME: [LegacyNullToEmptyString] is not allowed on nullable types as per the Web IDL spec. + // However, we only apply it to setters, so this works as a stop gap. + // Replace this with something like a special cased [LegacyNullToEmptyString]. + [LegacyNullToEmptyString] attribute DOMString? textContent; Node appendChild(Node node); [ImplementedAs=pre_insert] Node insertBefore(Node node, Node? child); |