From 9f5b1e66147c86c64929b49da5378be7eff17ef5 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Tue, 22 Aug 2023 16:28:06 +0100 Subject: [PATCH] LibWeb: Implement the `:read-only` and `:read-write` pseudo-classes --- ...ss-read-only-read-write-selectors-ref.html | 13 ++++++++ .../css-read-only-read-write-selectors.html | 13 ++++++++ Tests/LibWeb/Ref/manifest.json | 1 + .../Libraries/LibWeb/CSS/PseudoClasses.json | 6 ++++ .../Libraries/LibWeb/CSS/SelectorEngine.cpp | 32 +++++++++++++++++++ 5 files changed, 65 insertions(+) create mode 100644 Tests/LibWeb/Ref/css-read-only-read-write-selectors-ref.html create mode 100644 Tests/LibWeb/Ref/css-read-only-read-write-selectors.html diff --git a/Tests/LibWeb/Ref/css-read-only-read-write-selectors-ref.html b/Tests/LibWeb/Ref/css-read-only-read-write-selectors-ref.html new file mode 100644 index 00000000000..a01bac2daf5 --- /dev/null +++ b/Tests/LibWeb/Ref/css-read-only-read-write-selectors-ref.html @@ -0,0 +1,13 @@ + + + + +

Well hello friends

+

Well hello friends

diff --git a/Tests/LibWeb/Ref/css-read-only-read-write-selectors.html b/Tests/LibWeb/Ref/css-read-only-read-write-selectors.html new file mode 100644 index 00000000000..989e6dbf983 --- /dev/null +++ b/Tests/LibWeb/Ref/css-read-only-read-write-selectors.html @@ -0,0 +1,13 @@ + + + + +

Well hello friends

+

Well hello friends

diff --git a/Tests/LibWeb/Ref/manifest.json b/Tests/LibWeb/Ref/manifest.json index 60d30ac5b29..c2b8f0605c9 100644 --- a/Tests/LibWeb/Ref/manifest.json +++ b/Tests/LibWeb/Ref/manifest.json @@ -10,6 +10,7 @@ "css-lang-selector.html": "css-lang-selector-ref.html", "css-local-link-selector.html": "css-local-link-selector-ref.html", "css-gradients.html": "css-gradients-ref.html", + "css-read-only-read-write-selectors.html": "css-read-only-read-write-selectors-ref.html", "svg-symbol.html": "svg-symbol-ref.html", "svg-gradient-spreadMethod.html": "svg-gradient-spreadMethod-ref.html", "svg-radialGradient.html": "svg-radialGradient-ref.html" diff --git a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json index c74a23fb2ea..21b749d6ea5 100644 --- a/Userland/Libraries/LibWeb/CSS/PseudoClasses.json +++ b/Userland/Libraries/LibWeb/CSS/PseudoClasses.json @@ -98,6 +98,12 @@ "playing": { "argument": "" }, + "read-only": { + "argument": "" + }, + "read-write": { + "argument": "" + }, "root": { "argument": "" }, diff --git a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp index 1bbf994edc7..8486a66eca8 100644 --- a/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp +++ b/Userland/Libraries/LibWeb/CSS/SelectorEngine.cpp @@ -209,6 +209,34 @@ static inline DOM::Element const* next_sibling_with_same_tag_name(DOM::Element c return nullptr; } +// https://html.spec.whatwg.org/multipage/semantics-other.html#selector-read-write +static bool matches_read_write_pseudo_class(DOM::Element const& element) +{ + // The :read-write pseudo-class must match any element falling into one of the following categories, + // which for the purposes of Selectors are thus considered user-alterable: [SELECTORS] + // - input elements to which the readonly attribute applies, and that are mutable + // (i.e. that do not have the readonly attribute specified and that are not disabled) + if (is(element)) { + auto& input_element = static_cast(element); + if (input_element.has_attribute(HTML::AttributeNames::readonly)) + return false; + if (!input_element.enabled()) + return false; + return true; + } + // - textarea elements that do not have a readonly attribute, and that are not disabled + if (is(element)) { + auto& input_element = static_cast(element); + if (input_element.has_attribute(HTML::AttributeNames::readonly)) + return false; + if (!input_element.enabled()) + return false; + return true; + } + // - elements that are editing hosts or editable and are neither input elements nor textarea elements + return element.is_editable(); +} + static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoClassSelector const& pseudo_class, Optional style_sheet_for_rule, DOM::Element const& element, JS::GCPtr scope) { switch (pseudo_class.type) { @@ -465,6 +493,10 @@ static inline bool matches_pseudo_class(CSS::Selector::SimpleSelector::PseudoCla } VERIFY_NOT_REACHED(); } + case CSS::PseudoClass::ReadOnly: + return !matches_read_write_pseudo_class(element); + case CSS::PseudoClass::ReadWrite: + return matches_read_write_pseudo_class(element); } return false;