From 8ab25f8d8cf7b9b4dbdabdc4792da6de7d2b8e6c Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 21 Mar 2022 23:28:46 +0100 Subject: [PATCH] LibWeb: Implement Range.surroundContents(newParent) Here goes another Acid3 point :^) --- Userland/Libraries/LibWeb/DOM/Range.cpp | 38 +++++++++++++++++++++++++ Userland/Libraries/LibWeb/DOM/Range.h | 1 + Userland/Libraries/LibWeb/DOM/Range.idl | 1 + 3 files changed, 40 insertions(+) diff --git a/Userland/Libraries/LibWeb/DOM/Range.cpp b/Userland/Libraries/LibWeb/DOM/Range.cpp index 48e94863d1..d44e6fdfb7 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.cpp +++ b/Userland/Libraries/LibWeb/DOM/Range.cpp @@ -864,4 +864,42 @@ ExceptionOr Range::insert(NonnullRefPtr node) return {}; } +// https://dom.spec.whatwg.org/#dom-range-surroundcontents +ExceptionOr Range::surround_contents(NonnullRefPtr new_parent) +{ + // 1. If a non-Text node is partially contained in this, then throw an "InvalidStateError" DOMException. + Node* start_non_text_node = start_container(); + if (is(*start_non_text_node)) + start_non_text_node = start_non_text_node->parent_node(); + Node* end_non_text_node = end_container(); + if (is(*end_non_text_node)) + end_non_text_node = end_non_text_node->parent_node(); + if (start_non_text_node != end_non_text_node) + return InvalidStateError::create("Non-Text node is partially contained in range."); + + // 2. If newParent is a Document, DocumentType, or DocumentFragment node, then throw an "InvalidNodeTypeError" DOMException. + if (is(*new_parent) || is(*new_parent) || is(*new_parent)) + return InvalidNodeTypeError::create("Invalid parent node type"); + + // 3. Let fragment be the result of extracting this. + auto fragment_or_error = extract(); + if (fragment_or_error.is_exception()) + return fragment_or_error.exception(); + auto fragment = fragment_or_error.release_value(); + + // 4. If newParent has children, then replace all with null within newParent. + if (new_parent->has_children()) + new_parent->replace_all(nullptr); + + // 5. Insert newParent into this. + if (auto result = insert(new_parent); result.is_exception()) + return result.exception(); + + // 6. Append fragment to newParent. + new_parent->append_child(fragment); + + // 7. Select newParent within this. + return select(*new_parent); +} + } diff --git a/Userland/Libraries/LibWeb/DOM/Range.h b/Userland/Libraries/LibWeb/DOM/Range.h index 427254d3d8..ecd6fcf03f 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.h +++ b/Userland/Libraries/LibWeb/DOM/Range.h @@ -64,6 +64,7 @@ public: ExceptionOr> extract_contents(); ExceptionOr insert_node(NonnullRefPtr); + ExceptionOr surround_contents(NonnullRefPtr new_parent); String to_string() const; diff --git a/Userland/Libraries/LibWeb/DOM/Range.idl b/Userland/Libraries/LibWeb/DOM/Range.idl index ac4bca149a..44224ff729 100644 --- a/Userland/Libraries/LibWeb/DOM/Range.idl +++ b/Userland/Libraries/LibWeb/DOM/Range.idl @@ -26,6 +26,7 @@ interface Range : AbstractRange { [CEReactions, NewObject] DocumentFragment extractContents(); [CEReactions] undefined insertNode(Node node); + [CEReactions] undefined surroundContents(Node newParent); Range cloneRange(); undefined detach();