Skip to content

Commit 265c942

Browse files
An-n-yanico
authored andcommitted
LibWeb/CSS: Implement revert-layer
With the introduction of the cascade layer, the 5th CSS-wide keyword, `revert-layer`, has been added. (cherry picked from commit bea7eec)
1 parent e2a9a7f commit 265c942

File tree

8 files changed

+70
-5
lines changed

8 files changed

+70
-5
lines changed

Meta/Lagom/Tools/CodeGenerators/LibWeb/GenerateCSSKeyword.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ inline bool is_css_wide_keyword(StringView name)
7777
return name.equals_ignoring_ascii_case("inherit"sv)
7878
|| name.equals_ignoring_ascii_case("initial"sv)
7979
|| name.equals_ignoring_ascii_case("revert"sv)
80+
|| name.equals_ignoring_ascii_case("revert-layer"sv)
8081
|| name.equals_ignoring_ascii_case("unset"sv);
8182
}
8283
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
PASS: revert to base (first target)
2+
PASS: revert to base (second target)
3+
PASS: double revert (first target)
4+
PASS: double revert (second target)
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
<!DOCTYPE html>
2+
<target class="first"></target>
3+
<target class="second"></target>
4+
<script src="../include.js"></script>
5+
<script>
6+
test(() => {
7+
// In all test cases, the rule specified as "color: green" should win.
8+
var testCases = [
9+
{
10+
title: 'revert to base',
11+
style: `
12+
@layer base, special;
13+
@layer special { target { color: revert-layer; } target.second { color: green; } }
14+
@layer base { target { color: green; } target.second { color: red; } }
15+
`,
16+
},
17+
{
18+
title: 'double revert',
19+
style: `
20+
@layer layer1, layer2, layer3;
21+
@layer layer3 { target { color: revert-layer; } target.second { color: revert-layer; } }
22+
@layer layer2 { target { color: revert-layer; } target.second { color: green; } }
23+
@layer layer1 { target { color: green; } target.second { color: revert-layer; } }
24+
`,
25+
},
26+
];
27+
28+
for (let testCase of testCases) {
29+
const styleElement = document.createElement('style');
30+
styleElement.textContent = testCase['style'];
31+
document.head.append(styleElement);
32+
33+
var targets = document.querySelectorAll('target');
34+
for (let target of targets) {
35+
let actual = window.getComputedStyle(target).color;
36+
if (actual === 'rgb(0, 128, 0)') {
37+
println(`PASS: ${testCase['title']} (${target.classList[0]} target)`);
38+
} else {
39+
println(`FAIL: ${testCase['title']} (${target.classList[0]} target) - Expected 'rgb(0, 128, 0)', got '${actual}'`);
40+
}
41+
}
42+
43+
styleElement.remove();
44+
}
45+
46+
});
47+
</script>

Userland/Libraries/LibWeb/CSS/CSSStyleValue.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,10 +331,11 @@ class CSSStyleValue : public RefCounted<CSSStyleValue> {
331331

332332
// https://www.w3.org/TR/css-values-4/#common-keywords
333333
// https://drafts.csswg.org/css-cascade-4/#valdef-all-revert
334-
bool is_css_wide_keyword() const { return is_inherit() || is_initial() || is_revert() || is_unset(); }
334+
bool is_css_wide_keyword() const { return is_inherit() || is_initial() || is_revert() || is_unset() || is_revert_layer(); }
335335
bool is_inherit() const { return to_keyword() == Keyword::Inherit; }
336336
bool is_initial() const { return to_keyword() == Keyword::Initial; }
337337
bool is_revert() const { return to_keyword() == Keyword::Revert; }
338+
bool is_revert_layer() const { return to_keyword() == Keyword::RevertLayer; }
338339
bool is_unset() const { return to_keyword() == Keyword::Unset; }
339340

340341
bool has_auto() const;

Userland/Libraries/LibWeb/CSS/Keywords.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,7 @@
308308
"repeat-y",
309309
"reverse",
310310
"revert",
311+
"revert-layer",
311312
"ridge",
312313
"right",
313314
"round",

Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1757,7 +1757,10 @@ RefPtr<CSSStyleValue> Parser::parse_builtin_value(TokenStream<ComponentValue>& t
17571757
transaction.commit();
17581758
return CSSKeywordValue::create(Keyword::Revert);
17591759
}
1760-
// FIXME: Implement `revert-layer` from CSS-CASCADE-5.
1760+
if (ident.equals_ignoring_ascii_case("revert-layer"sv)) {
1761+
transaction.commit();
1762+
return CSSKeywordValue::create(Keyword::RevertLayer);
1763+
}
17611764
}
17621765

17631766
return nullptr;

Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ void StyleComputer::for_each_property_expanding_shorthands(PropertyID property_i
789789
void StyleComputer::set_property_expanding_shorthands(StyleProperties& style, CSS::PropertyID property_id, CSSStyleValue const& value, CSS::CSSStyleDeclaration const* declaration, StyleProperties const& style_for_revert, Important important)
790790
{
791791
for_each_property_expanding_shorthands(property_id, value, AllowUnresolved::No, [&](PropertyID shorthand_id, CSSStyleValue const& shorthand_value) {
792-
if (shorthand_value.is_revert()) {
792+
if (shorthand_value.is_revert() || shorthand_value.is_revert_layer()) {
793793
auto const& property_in_previous_cascade_origin = style_for_revert.m_data->m_property_values[to_underlying(shorthand_id)];
794794
if (property_in_previous_cascade_origin) {
795795
style.set_property(shorthand_id, *property_in_previous_cascade_origin, StyleProperties::Inherited::No, important);
@@ -809,7 +809,7 @@ void StyleComputer::set_all_properties(DOM::Element& element, Optional<CSS::Sele
809809
for (auto i = to_underlying(CSS::first_longhand_property_id); i <= to_underlying(CSS::last_longhand_property_id); ++i) {
810810
auto property_id = (CSS::PropertyID)i;
811811

812-
if (value.is_revert()) {
812+
if (value.is_revert() || value.is_revert_layer()) {
813813
style.revert_property(property_id, style_for_revert);
814814
continue;
815815
}
@@ -901,8 +901,12 @@ static void cascade_custom_properties(DOM::Element& element, Optional<CSS::Selec
901901
custom_properties.ensure_capacity(needed_capacity);
902902

903903
for (auto const& matching_rule : matching_rules) {
904-
for (auto const& it : matching_rule.rule->declaration().custom_properties())
904+
for (auto const& it : matching_rule.rule->declaration().custom_properties()) {
905+
auto style_value = it.value.value;
906+
if (style_value->is_revert_layer())
907+
continue;
905908
custom_properties.set(it.key, it.value);
909+
}
906910
}
907911

908912
if (!pseudo_element.has_value()) {

Userland/Libraries/LibWeb/CSS/StyleValues/CSSKeywordValue.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ class CSSKeywordValue : public StyleValueWithDefaultOperators<CSSKeywordValue> {
3333
static ValueComparingNonnullRefPtr<CSSKeywordValue> const revert_instance = adopt_ref(*new (nothrow) CSSKeywordValue(Keyword::Revert));
3434
return revert_instance;
3535
}
36+
case Keyword::RevertLayer: {
37+
static ValueComparingNonnullRefPtr<CSSKeywordValue> const revert_layer_instance = adopt_ref(*new (nothrow) CSSKeywordValue(Keyword::RevertLayer));
38+
return revert_layer_instance;
39+
}
3640
case Keyword::Unset: {
3741
static ValueComparingNonnullRefPtr<CSSKeywordValue> const unset_instance = adopt_ref(*new (nothrow) CSSKeywordValue(Keyword::Unset));
3842
return unset_instance;

0 commit comments

Comments
 (0)