Browse Source

LibWeb: Add attribute list that must always be compared without casing

Edwin Hoksberg 1 year ago
parent
commit
2b30414c1d

+ 12 - 0
Tests/LibWeb/Ref/css-case-insensitive-html-attributes-selector.html

@@ -0,0 +1,12 @@
+<!doctype html>
+<link rel="match" href="reference/css-case-insensitive-html-attributes-selector-ref.html" />
+<style>
+    div[type=one] { /* 'type' is a case-insensitive html attribute */
+        background: red;
+    }
+    div[test=two] { /* 'test' is NOT a case-insensitive html attribute */
+        background: green;
+    }
+</style>
+<div type="ONE">I have a red background</div>
+<div type="TWO">I don't have a green background</div>

+ 8 - 0
Tests/LibWeb/Ref/reference/css-case-insensitive-html-attributes-selector-ref.html

@@ -0,0 +1,8 @@
+<!doctype html>
+<style>
+    div[type=one] {
+        background: red;
+    }
+</style>
+<div type="one">I have a red background</div>
+<div type="two">I don't have a green background</div>

+ 50 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -75,6 +75,56 @@ public:
 
     [[nodiscard]] LengthOrCalculated parse_as_sizes_attribute();
 
+    // https://html.spec.whatwg.org/multipage/semantics-other.html#case-sensitivity-of-selectors
+    static constexpr Array case_insensitive_html_attributes = {
+        "accept"sv,
+        "accept-charset"sv,
+        "align"sv,
+        "alink"sv,
+        "axis"sv,
+        "bgcolor"sv,
+        "charset"sv,
+        "checked"sv,
+        "clear"sv,
+        "codetype"sv,
+        "color"sv,
+        "compact"sv,
+        "declare"sv,
+        "defer"sv,
+        "dir"sv,
+        "direction"sv,
+        "disabled"sv,
+        "enctype"sv,
+        "face"sv,
+        "frame"sv,
+        "hreflang"sv,
+        "http-equiv"sv,
+        "lang"sv,
+        "language"sv,
+        "link"sv,
+        "media"sv,
+        "method"sv,
+        "multiple"sv,
+        "nohref"sv,
+        "noresize"sv,
+        "noshade"sv,
+        "nowrap"sv,
+        "readonly"sv,
+        "rel"sv,
+        "rev"sv,
+        "rules"sv,
+        "scope"sv,
+        "scrolling"sv,
+        "selected"sv,
+        "shape"sv,
+        "target"sv,
+        "text"sv,
+        "type"sv,
+        "valign"sv,
+        "valuetype"sv,
+        "vlink"sv,
+    };
+
 private:
     Parser(ParsingContext const&, Vector<Token>);
 

+ 5 - 2
Userland/Libraries/LibWeb/CSS/Parser/SelectorParsing.cpp

@@ -226,6 +226,7 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_attribute_simple_se
         dbgln_if(CSS_PARSER_DEBUG, "Expected qualified-name for attribute name, got: '{}'", attribute_tokens.peek_token().to_debug_string());
         return ParseError::SyntaxError;
     }
+    auto qualified_name = maybe_qualified_name.release_value();
 
     Selector::SimpleSelector simple_selector {
         .type = Selector::SimpleSelector::Type::Attribute,
@@ -236,8 +237,10 @@ Parser::ParseErrorOr<Selector::SimpleSelector> Parser::parse_attribute_simple_se
             // they are converted to lowercase, so we do that here too. If we want to be
             // correct with XML later, we'll need to keep the original case and then do
             // a case-insensitive compare later.
-            .qualified_name = maybe_qualified_name.release_value(),
-            .case_type = Selector::SimpleSelector::Attribute::CaseType::DefaultMatch,
+            .qualified_name = qualified_name,
+            .case_type = case_insensitive_html_attributes.contains_slow(qualified_name.name.lowercase_name)
+                ? Selector::SimpleSelector::Attribute::CaseType::CaseInsensitiveMatch
+                : Selector::SimpleSelector::Attribute::CaseType::DefaultMatch,
         }
     };