From a232395b7738df4a10dd64ef6b01530a64e1a8e3 Mon Sep 17 00:00:00 2001 From: Karol Kosek Date: Thu, 2 Jun 2022 18:00:51 +0200 Subject: [PATCH] LibWeb: Check recursively if CSS functions contain `var()` or `attr()` Previously, `var()` inside functions like `rgb()` wasn't resolved. This will set the background color for badges in the New category on https://ports.serenityos.net. :^) --- Base/res/html/misc/custom-properties.html | 17 +++++++++++++++++ Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 15 ++++++++++++--- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/Base/res/html/misc/custom-properties.html b/Base/res/html/misc/custom-properties.html index 253a4557de..308f7e9614 100644 --- a/Base/res/html/misc/custom-properties.html +++ b/Base/res/html/misc/custom-properties.html @@ -45,6 +45,11 @@ border: var(--border); } + .test-inside-a-function { + --blue: 255; + background-color: rgb(255, 0, var(--blue)); + } + .test-mixed { background: var(--background-color) url("background-repeat.png") var(--background-position) no-repeat; } @@ -178,6 +183,18 @@ This should have a 10px solid orange border +
+        .test-inside-a-function {
+            --blue: 255;
+            background-color: rgb(255, 0, var(--blue));
+        }
+    
+ +
+
.test-inside-a-function
+ This should be fuchsia +
+

Mixed var()

         :root {
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
index 17f95c4eb0..27bc80156e 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
@@ -4962,9 +4962,18 @@ RefPtr Parser::parse_as_css_value(PropertyID property_id)
 
 Parser::ParseErrorOr> Parser::parse_css_value(PropertyID property_id, TokenStream& tokens)
 {
-    auto block_contains_var_or_attr = [](Block const& block, auto&& recurse) -> bool {
+    auto function_contains_var_or_attr = [](Function const& function, auto&& recurse) -> bool {
+        if (function.name().equals_ignoring_case("var"sv) || function.name().equals_ignoring_case("attr"sv))
+            return true;
+        for (auto const& token : function.values()) {
+            if (token.is_function() && recurse(token.function(), recurse))
+                return true;
+        }
+        return false;
+    };
+    auto block_contains_var_or_attr = [function_contains_var_or_attr](Block const& block, auto&& recurse) -> bool {
         for (auto const& token : block.values()) {
-            if (token.is_function() && (token.function().name().equals_ignoring_case("var"sv) || token.function().name().equals_ignoring_case("attr"sv)))
+            if (token.is_function() && function_contains_var_or_attr(token.function(), function_contains_var_or_attr))
                 return true;
             if (token.is_block() && recurse(token.block(), recurse))
                 return true;
@@ -4993,7 +5002,7 @@ Parser::ParseErrorOr> Parser::parse_css_value(Property
         }
 
         if (!contains_var_or_attr) {
-            if (token.is_function() && (token.function().name().equals_ignoring_case("var"sv) || token.function().name().equals_ignoring_case("attr"sv)))
+            if (token.is_function() && function_contains_var_or_attr(token.function(), function_contains_var_or_attr))
                 contains_var_or_attr = true;
             else if (token.is_block() && block_contains_var_or_attr(token.block(), block_contains_var_or_attr))
                 contains_var_or_attr = true;