summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibWeb/DOM/CharacterData.h2
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.cpp41
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.h5
-rw-r--r--Userland/Libraries/LibWeb/DOM/Node.idl6
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);