diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index 9800437210c..a172759bbfe 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -153,10 +153,55 @@ void HTMLElement::set_inner_text(StringView text) set_needs_style_update(true); } -// https://html.spec.whatwg.org/multipage/dom.html#the-innertext-idl-attribute:dom-outertext-2 -WebIDL::ExceptionOr HTMLElement::set_outer_text(String) +// https://html.spec.whatwg.org/multipage/dom.html#merge-with-the-next-text-node +static void merge_with_the_next_text_node(DOM::Text& node) { - dbgln("FIXME: Implement HTMLElement::set_outer_text()"); + // 1. Let next be node's next sibling. + auto next = node.next_sibling(); + + // 2. If next is not a Text node, then return. + if (!is(next)) + return; + + // 3. Replace data with node, node's data's length, 0, and next's data. + MUST(node.replace_data(node.length_in_utf16_code_units(), 0, static_cast(*next).data())); + + // 4. Remove next. + next->remove(); +} + +// https://html.spec.whatwg.org/multipage/dom.html#the-innertext-idl-attribute:dom-outertext-2 +WebIDL::ExceptionOr HTMLElement::set_outer_text(String const& value) +{ + // 1. If this's parent is null, then throw a "NoModificationAllowedError" DOMException. + if (!parent()) + return WebIDL::NoModificationAllowedError::create(realm(), "setOuterText: parent is null"_string); + + // 2. Let next be this's next sibling. + auto* next = next_sibling(); + + // 3. Let previous be this's previous sibling. + auto* previous = previous_sibling(); + + // 4. Let fragment be the rendered text fragment for the given value given this's node document. + auto fragment = rendered_text_fragment(value); + + // 5. If fragment has no children, then append a new Text node whose data is the empty string and node document is this's node document to fragment. + if (!fragment->has_children()) + MUST(fragment->append_child(document().create_text_node(String {}))); + + // 6. Replace this with fragment within this's parent. + MUST(parent()->replace_child(fragment, *this)); + + // 7. If next is non-null and next's previous sibling is a Text node, then merge with the next text node given next's previous sibling. + if (next && is(next->previous_sibling())) + merge_with_the_next_text_node(static_cast(*next->previous_sibling())); + + // 8. If previous is a Text node, then merge with the next text node given previous. + if (is(previous)) + merge_with_the_next_text_node(static_cast(*previous)); + + set_needs_style_update(true); return {}; } diff --git a/Libraries/LibWeb/HTML/HTMLElement.h b/Libraries/LibWeb/HTML/HTMLElement.h index feb47862570..6e29a48b105 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Libraries/LibWeb/HTML/HTMLElement.h @@ -45,7 +45,7 @@ public: void set_inner_text(StringView); [[nodiscard]] String outer_text(); - WebIDL::ExceptionOr set_outer_text(String); + WebIDL::ExceptionOr set_outer_text(String const&); int offset_top() const; int offset_left() const; diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/dom/elements/the-innertext-and-outertext-properties/outertext-setter.txt b/Tests/LibWeb/Text/expected/wpt-import/html/dom/elements/the-innertext-and-outertext-properties/outertext-setter.txt index 8b63fe2ff8a..ced1f9f078b 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/html/dom/elements/the-innertext-and-outertext-properties/outertext-setter.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/html/dom/elements/the-innertext-and-outertext-properties/outertext-setter.txt @@ -6,49 +6,48 @@ Rerun Found 43 tests -2 Pass -41 Fail +43 Pass Details -Result Test Name MessageFail Replacing a node and merging with the previous text node -Fail Replacing a node and merging with the following text node -Fail Replacing a node and merging with the previous and following text node -Fail Only merges with the previous and following text nodes, does not completely normalize -Fail Empty string -Fail Empty string with surrounding text nodes -Fail Setting outerText to a bunch of newlines creates a bunch of
s with no text nodes -Fail Removing a node -Fail Detached node -Fail Simplest possible test -Fail Newlines convert to
in non-white-space:pre elements -Fail Newlines convert to
in
 element	
-Fail	Newlines convert to 
in