diff --git a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp index 63abb7f0051..f85a3a74647 100644 --- a/Libraries/LibWeb/Editing/Internal/Algorithms.cpp +++ b/Libraries/LibWeb/Editing/Internal/Algorithms.cpp @@ -816,11 +816,10 @@ bool is_editing_host(GC::Ref node) // An editing host is either an HTML element with its contenteditable attribute in the true // state or plaintext-only state, or a child HTML element of a Document whose design mode // enabled is true. - // FIXME: check contenteditable "plaintext-only" if (!is(*node)) return false; auto const& html_element = static_cast(*node); - return html_element.content_editable() == "true"sv || node->document().design_mode_enabled_state(); + return html_element.content_editable().is_one_of("true"sv, "plaintext-only"sv) || node->document().design_mode_enabled_state(); } // https://w3c.github.io/editing/docs/execCommand/#element-with-inline-contents diff --git a/Libraries/LibWeb/HTML/HTMLElement.cpp b/Libraries/LibWeb/HTML/HTMLElement.cpp index 1cd5e041121..97a82fb24cc 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.cpp +++ b/Libraries/LibWeb/HTML/HTMLElement.cpp @@ -88,6 +88,7 @@ bool HTMLElement::is_editable() const { switch (m_content_editable_state) { case ContentEditableState::True: + case ContentEditableState::PlaintextOnly: return true; case ContentEditableState::False: return false; @@ -100,7 +101,8 @@ bool HTMLElement::is_editable() const bool HTMLElement::is_focusable() const { - return m_content_editable_state == ContentEditableState::True; + return m_content_editable_state == ContentEditableState::True + || m_content_editable_state == ContentEditableState::PlaintextOnly; } // https://html.spec.whatwg.org/multipage/interaction.html#dom-iscontenteditable @@ -118,6 +120,8 @@ StringView HTMLElement::content_editable() const return "true"sv; case ContentEditableState::False: return "false"sv; + case ContentEditableState::PlaintextOnly: + return "plaintext-only"sv; case ContentEditableState::Inherit: return "inherit"sv; } @@ -135,11 +139,15 @@ WebIDL::ExceptionOr HTMLElement::set_content_editable(StringView content_e MUST(set_attribute(HTML::AttributeNames::contenteditable, "true"_string)); return {}; } + if (content_editable.equals_ignoring_ascii_case("plaintext-only"sv)) { + MUST(set_attribute(HTML::AttributeNames::contenteditable, "plaintext-only"_string)); + return {}; + } if (content_editable.equals_ignoring_ascii_case("false"sv)) { MUST(set_attribute(HTML::AttributeNames::contenteditable, "false"_string)); return {}; } - return WebIDL::SyntaxError::create(realm(), "Invalid contentEditable value, must be 'true', 'false', or 'inherit'"_string); + return WebIDL::SyntaxError::create(realm(), "Invalid contentEditable value, must be 'true', 'false', 'plaintext-only' or 'inherit'"_string); } // https://html.spec.whatwg.org/multipage/dom.html#set-the-inner-text-steps @@ -602,18 +610,20 @@ void HTMLElement::attribute_changed(FlyString const& name, Optional cons if (name == HTML::AttributeNames::contenteditable) { if (!value.has_value()) { + // No value maps to the "inherit" state. m_content_editable_state = ContentEditableState::Inherit; + } else if (value->is_empty() || value->equals_ignoring_ascii_case("true"sv)) { + // "true", an empty string or a missing value map to the "true" state. + m_content_editable_state = ContentEditableState::True; + } else if (value->equals_ignoring_ascii_case("false"sv)) { + // "false" maps to the "false" state. + m_content_editable_state = ContentEditableState::False; + } else if (value->equals_ignoring_ascii_case("plaintext-only"sv)) { + // "plaintext-only" maps to the "plaintext-only" state. + m_content_editable_state = ContentEditableState::PlaintextOnly; } else { - if (value->is_empty() || value->equals_ignoring_ascii_case("true"sv)) { - // "true", an empty string or a missing value map to the "true" state. - m_content_editable_state = ContentEditableState::True; - } else if (value->equals_ignoring_ascii_case("false"sv)) { - // "false" maps to the "false" state. - m_content_editable_state = ContentEditableState::False; - } else { - // Having no such attribute or an invalid value maps to the "inherit" state. - m_content_editable_state = ContentEditableState::Inherit; - } + // Having an invalid value maps to the "inherit" state. + m_content_editable_state = ContentEditableState::Inherit; } } diff --git a/Libraries/LibWeb/HTML/HTMLElement.h b/Libraries/LibWeb/HTML/HTMLElement.h index 099e06aa41d..44abde261ed 100644 --- a/Libraries/LibWeb/HTML/HTMLElement.h +++ b/Libraries/LibWeb/HTML/HTMLElement.h @@ -105,9 +105,11 @@ private: // https://html.spec.whatwg.org/multipage/custom-elements.html#attached-internals GC::Ptr m_attached_internals; + // https://html.spec.whatwg.org/#attr-contenteditable enum class ContentEditableState { True, False, + PlaintextOnly, Inherit, }; ContentEditableState m_content_editable_state { ContentEditableState::Inherit }; diff --git a/Tests/LibWeb/Text/expected/wpt-import/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.txt b/Tests/LibWeb/Text/expected/wpt-import/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.txt new file mode 100644 index 00000000000..d6b5bff052d --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.txt @@ -0,0 +1,34 @@ +Summary + +Harness status: OK + +Rerun + +Found 24 tests + +24 Pass +Details +Result Test Name MessagePass IDL attribute getter for attribute value "true" +Pass IDL attribute setter for value "true" +Pass IDL attribute getter for attribute value "TRUE" +Pass IDL attribute setter for value "TRUE" +Pass IDL attribute getter for attribute value "false" +Pass IDL attribute setter for value "false" +Pass IDL attribute getter for attribute value "FALSE" +Pass IDL attribute setter for value "FALSE" +Pass IDL attribute getter for attribute value "inherit" +Pass IDL attribute setter for value "inherit" +Pass IDL attribute getter for attribute value "INHERIT" +Pass IDL attribute setter for value "INHERIT" +Pass IDL attribute getter for attribute value "plaintext-only" +Pass IDL attribute setter for value "plaintext-only" +Pass IDL attribute getter for attribute value "PLAINTEXT-ONLY" +Pass IDL attribute setter for value "PLAINTEXT-ONLY" +Pass IDL attribute getter for attribute value "foobar" +Pass IDL attribute setter for value "foobar" +Pass IDL attribute getter for attribute value "falſe" +Pass IDL attribute setter for value "falſe" +Pass IDL attribute getter for attribute value "plaıntext-only" +Pass IDL attribute setter for value "plaıntext-only" +Pass IDL attribute getter for attribute value "plaİntext-only" +Pass IDL attribute setter for value "plaİntext-only" diff --git a/Tests/LibWeb/Text/input/wpt-import/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.html b/Tests/LibWeb/Text/input/wpt-import/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.html new file mode 100644 index 00000000000..e815a69e773 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/html/editing/editing-0/contenteditable/contenteditable-enumerated-ascii-case-insensitive.html @@ -0,0 +1,45 @@ + + + + + + + + +