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. :^)
This commit is contained in:
Karol Kosek 2022-06-02 18:00:51 +02:00 committed by Andreas Kling
parent 1072d523e2
commit a232395b77
2 changed files with 29 additions and 3 deletions

View file

@ -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
</div>
<pre>
.test-inside-a-function {
--blue: 255;
background-color: rgb(255, 0, var(--blue));
}
</pre>
<div class="box test-inside-a-function">
<pre>.test-inside-a-function</pre>
This should be fuchsia
</div>
<h2>Mixed var()</h2>
<pre>
:root {

View file

@ -4962,9 +4962,18 @@ RefPtr<StyleValue> Parser::parse_as_css_value(PropertyID property_id)
Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> Parser::parse_css_value(PropertyID property_id, TokenStream<ComponentValue>& 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<NonnullRefPtr<StyleValue>> 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;