mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-09-20 16:28:54 +00:00
LibWeb: Reset border-image
to initial value when using border
Also includes associated handling for serialization of the `border` shorthand.
This commit is contained in:
parent
588c611e7e
commit
50239b58aa
Notes:
github-actions[bot]
2025-09-15 07:43:28 +00:00
Author: https://github.com/Calme1709
Commit: 50239b58aa
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/6199
Reviewed-by: https://github.com/tcl3 ✅
8 changed files with 161 additions and 14 deletions
|
@ -1570,6 +1570,7 @@ RefPtr<StyleValue const> Parser::parse_single_background_size_value(PropertyID p
|
|||
return BackgroundSizeStyleValue::create(x_size.release_value(), y_size.release_value());
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-backgrounds-3/#propdef-border
|
||||
RefPtr<StyleValue const> Parser::parse_border_value(PropertyID property_id, TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
RefPtr<StyleValue const> border_width;
|
||||
|
@ -1639,11 +1640,17 @@ RefPtr<StyleValue const> Parser::parse_border_value(PropertyID property_id, Toke
|
|||
if (!border_color)
|
||||
border_color = property_initial_value(color_property);
|
||||
|
||||
// FIXME: Also reset border-image, in line with the spec: https://www.w3.org/TR/css-backgrounds-3/#border-shorthands
|
||||
transaction.commit();
|
||||
|
||||
if (first_is_one_of(property_id, PropertyID::BorderBlock, PropertyID::BorderInline))
|
||||
return ShorthandStyleValue::create(property_id,
|
||||
{ width_property, style_property, color_property },
|
||||
{ border_width.release_nonnull(), border_style.release_nonnull(), border_color.release_nonnull() });
|
||||
|
||||
// The border shorthand also resets border-image to its initial value
|
||||
return ShorthandStyleValue::create(property_id,
|
||||
{ width_property, style_property, color_property },
|
||||
{ border_width.release_nonnull(), border_style.release_nonnull(), border_color.release_nonnull() });
|
||||
{ width_property, style_property, color_property, PropertyID::BorderImage },
|
||||
{ border_width.release_nonnull(), border_style.release_nonnull(), border_color.release_nonnull(), property_initial_value(PropertyID::BorderImage) });
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/css-backgrounds/#border-image
|
||||
|
|
|
@ -498,7 +498,8 @@
|
|||
"longhands": [
|
||||
"border-width",
|
||||
"border-style",
|
||||
"border-color"
|
||||
"border-color",
|
||||
"border-image"
|
||||
],
|
||||
"needs-layout-for-getcomputedstyle": true
|
||||
},
|
||||
|
|
|
@ -239,17 +239,45 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
return MUST(builder.to_string());
|
||||
}
|
||||
case PropertyID::Border: {
|
||||
// `border` only has a reasonable value if border-image is it's initial value (in which case it is omitted)
|
||||
if (!longhand(PropertyID::BorderImage)->equals(property_initial_value(PropertyID::BorderImage)))
|
||||
return ""_string;
|
||||
|
||||
auto all_longhands_same_value = [](ValueComparingRefPtr<StyleValue const> const& shorthand) -> bool {
|
||||
auto longhands = shorthand->as_shorthand().values();
|
||||
|
||||
return all_of(longhands, [&](auto const& longhand) { return longhand == longhands[0]; });
|
||||
};
|
||||
|
||||
auto const& border_width = longhand(PropertyID::BorderWidth);
|
||||
auto const& border_style = longhand(PropertyID::BorderStyle);
|
||||
auto const& border_color = longhand(PropertyID::BorderColor);
|
||||
|
||||
// `border` only has a reasonable value if all four sides are the same.
|
||||
if (!all_longhands_same_value(longhand(PropertyID::BorderWidth)) || !all_longhands_same_value(longhand(PropertyID::BorderStyle)) || !all_longhands_same_value(longhand(PropertyID::BorderColor)))
|
||||
if (!all_longhands_same_value(border_width) || !all_longhands_same_value(border_style) || !all_longhands_same_value(border_color))
|
||||
return ""_string;
|
||||
|
||||
return default_to_string();
|
||||
StringBuilder builder;
|
||||
|
||||
if (!border_width->equals(property_initial_value(PropertyID::BorderWidth)))
|
||||
builder.appendff("{}", border_width->to_string(mode));
|
||||
|
||||
if (!border_style->equals(property_initial_value(PropertyID::BorderStyle))) {
|
||||
if (!builder.is_empty())
|
||||
builder.append(' ');
|
||||
builder.appendff("{}", border_style->to_string(mode));
|
||||
}
|
||||
|
||||
if (!border_color->equals(property_initial_value(PropertyID::BorderColor))) {
|
||||
if (!builder.is_empty())
|
||||
builder.append(' ');
|
||||
builder.appendff("{}", border_color->to_string(mode));
|
||||
}
|
||||
|
||||
if (builder.is_empty())
|
||||
return border_width->to_string(mode);
|
||||
|
||||
return builder.to_string_without_validation();
|
||||
}
|
||||
case PropertyID::BorderImage: {
|
||||
auto source = longhand(PropertyID::BorderImageSource);
|
||||
|
|
|
@ -30,7 +30,7 @@ Setting border: '1px solid red'; becomes...
|
|||
border-style: 'solid'
|
||||
border-color: 'red'
|
||||
border: '1px solid red'
|
||||
e.style.length: 12
|
||||
e.style.length: 17
|
||||
> [0] border-top-width
|
||||
> [1] border-right-width
|
||||
> [2] border-bottom-width
|
||||
|
@ -43,4 +43,9 @@ Setting border: '1px solid red'; becomes...
|
|||
> [9] border-right-color
|
||||
> [10] border-bottom-color
|
||||
> [11] border-left-color
|
||||
> [12] border-image-source
|
||||
> [13] border-image-slice
|
||||
> [14] border-image-width
|
||||
> [15] border-image-outset
|
||||
> [16] border-image-repeat
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 36 tests
|
||||
|
||||
36 Pass
|
||||
Pass e.style['border'] = "2px solid color-mix(42deg)" should not set the property value
|
||||
Pass e.style['border'] = "2px solid color-contrast(42deg)" should not set the property value
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-bottom-color
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-bottom-style
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-bottom-width
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-image-outset
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-image-repeat
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-image-slice
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-image-source
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-image-width
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-left-color
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-left-style
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-left-width
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-right-color
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-right-style
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-right-width
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-top-color
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-top-style
|
||||
Pass e.style['border'] = "5px dotted blue" should set border-top-width
|
||||
Pass e.style['border'] = "5px dotted blue" should not set unrelated longhands
|
||||
Pass e.style['border-top'] = "thin" should set border-top-color
|
||||
Pass e.style['border-top'] = "thin" should set border-top-style
|
||||
Pass e.style['border-top'] = "thin" should set border-top-width
|
||||
Pass e.style['border-top'] = "thin" should not set unrelated longhands
|
||||
Pass e.style['border-right'] = "double" should set border-right-color
|
||||
Pass e.style['border-right'] = "double" should set border-right-style
|
||||
Pass e.style['border-right'] = "double" should set border-right-width
|
||||
Pass e.style['border-right'] = "double" should not set unrelated longhands
|
||||
Pass e.style['border-bottom'] = "green" should set border-bottom-color
|
||||
Pass e.style['border-bottom'] = "green" should set border-bottom-style
|
||||
Pass e.style['border-bottom'] = "green" should set border-bottom-width
|
||||
Pass e.style['border-bottom'] = "green" should not set unrelated longhands
|
||||
Pass e.style['border-left'] = "1px dotted red" should set border-left-color
|
||||
Pass e.style['border-left'] = "1px dotted red" should set border-left-style
|
||||
Pass e.style['border-left'] = "1px dotted red" should set border-left-width
|
||||
Pass e.style['border-left'] = "1px dotted red" should not set unrelated longhands
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 3 tests
|
||||
|
||||
1 Pass
|
||||
2 Fail
|
||||
Fail Declaration with border longhands is not serialized to a border shorthand declaration.
|
||||
Fail Declaration with border longhands and border-image is not serialized to a border shorthand declaration.
|
||||
3 Pass
|
||||
Pass Declaration with border longhands is not serialized to a border shorthand declaration.
|
||||
Pass Declaration with border longhands and border-image is not serialized to a border shorthand declaration.
|
||||
Pass Border shorthand is serialized correctly if all border-image-* are set to their initial specified values.
|
|
@ -2,13 +2,13 @@ Harness status: OK
|
|||
|
||||
Found 20 tests
|
||||
|
||||
14 Pass
|
||||
6 Fail
|
||||
15 Pass
|
||||
5 Fail
|
||||
Pass The serialization of border: 1px; border-top: 1px; should be canonical.
|
||||
Pass The serialization of border: 1px solid red; should be canonical.
|
||||
Pass The serialization of border: 1px red; should be canonical.
|
||||
Pass The serialization of border: red; should be canonical.
|
||||
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.
|
||||
Pass The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; border-image: none; should be canonical.
|
||||
Fail The serialization of border-top: 1px; border-right: 1px; border-bottom: 1px; border-left: 1px; should be canonical.
|
||||
Fail The serialization of border-top: 1px; border-right: 2px; border-bottom: 3px; border-left: 4px; should be canonical.
|
||||
Fail The serialization of border: 1px; border-top: 2px; should be canonical.
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Backgrounds and Borders Module Level 3: border sets longhands</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-backgrounds/#border-shorthands">
|
||||
<meta name="assert" content="border supports the full grammar '<line-width> || <line-style> || <color>'.">
|
||||
<meta name="assert" content="The border shorthand also resets border-image to its initial value.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/shorthand-testcommon.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
|
||||
test_invalid_value('border', '2px solid color-mix(42deg)');
|
||||
test_invalid_value('border', '2px solid color-contrast(42deg)');
|
||||
|
||||
test_shorthand_value('border', '5px dotted blue', {
|
||||
'border-top-width': '5px',
|
||||
'border-right-width': '5px',
|
||||
'border-bottom-width': '5px',
|
||||
'border-left-width': '5px',
|
||||
'border-top-style': 'dotted',
|
||||
'border-right-style': 'dotted',
|
||||
'border-bottom-style': 'dotted',
|
||||
'border-left-style': 'dotted',
|
||||
'border-top-color': 'blue',
|
||||
'border-right-color': 'blue',
|
||||
'border-bottom-color': 'blue',
|
||||
'border-left-color': 'blue',
|
||||
|
||||
'border-image-source': 'none',
|
||||
'border-image-slice': '100%',
|
||||
'border-image-width': '1',
|
||||
'border-image-outset': '0',
|
||||
'border-image-repeat': 'stretch'
|
||||
});
|
||||
|
||||
test_shorthand_value('border-top', 'thin', {
|
||||
'border-top-width': 'thin',
|
||||
'border-top-style': 'none',
|
||||
'border-top-color': 'currentcolor'
|
||||
});
|
||||
|
||||
test_shorthand_value('border-right', 'double', {
|
||||
'border-right-width': 'medium',
|
||||
'border-right-style': 'double',
|
||||
'border-right-color': 'currentcolor'
|
||||
});
|
||||
|
||||
test_shorthand_value('border-bottom', 'green', {
|
||||
'border-bottom-width': 'medium',
|
||||
'border-bottom-style': 'none',
|
||||
'border-bottom-color': 'green'
|
||||
});
|
||||
|
||||
test_shorthand_value('border-left', '1px dotted red', {
|
||||
'border-left-width': '1px',
|
||||
'border-left-style': 'dotted',
|
||||
'border-left-color': 'red'
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue