mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-29 20:29:18 +00:00
LibWeb: Generically serialize "positional-value-list-shorthand"s
We were previously handling this ad-hoc via logic in `get_property_internal` but this didn't cover all contexts (for instance `CSSStyleProperties::serialized`. Gains us 9 more WPT tests as we now cover properties which weren't included in the previous ad-hoc approach.
This commit is contained in:
parent
9ed85ddd63
commit
927cd969b2
Notes:
github-actions[bot]
2025-07-15 13:27:25 +00:00
Author: https://github.com/Calme1709
Commit: 927cd969b2
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5386
Reviewed-by: https://github.com/AtkinsSJ ✅
14 changed files with 234 additions and 115 deletions
|
@ -425,44 +425,6 @@ StringView CSSStyleProperties::get_property_priority(StringView property_name) c
|
|||
return maybe_property->important == Important::Yes ? "important"sv : ""sv;
|
||||
}
|
||||
|
||||
static Optional<StyleProperty> style_property_for_sided_shorthand(PropertyID property_id, Optional<StyleProperty> const& top, Optional<StyleProperty> const& right, Optional<StyleProperty> const& bottom, Optional<StyleProperty> const& left)
|
||||
{
|
||||
if (!top.has_value() || !right.has_value() || !bottom.has_value() || !left.has_value())
|
||||
return {};
|
||||
|
||||
if (top->important != right->important || top->important != bottom->important || top->important != left->important)
|
||||
return {};
|
||||
|
||||
ValueComparingNonnullRefPtr<CSSStyleValue const> const top_value { top->value };
|
||||
ValueComparingNonnullRefPtr<CSSStyleValue const> const right_value { right->value };
|
||||
ValueComparingNonnullRefPtr<CSSStyleValue const> const bottom_value { bottom->value };
|
||||
ValueComparingNonnullRefPtr<CSSStyleValue const> const left_value { left->value };
|
||||
|
||||
bool const top_and_bottom_same = top_value == bottom_value;
|
||||
bool const left_and_right_same = left_value == right_value;
|
||||
|
||||
if ((top_value->is_css_wide_keyword() || right_value->is_css_wide_keyword() || bottom_value->is_css_wide_keyword() || left_value->is_css_wide_keyword()) && (!top_and_bottom_same || !left_and_right_same || top_value != left_value))
|
||||
return {};
|
||||
|
||||
RefPtr<CSSStyleValue const> value;
|
||||
|
||||
if (top_and_bottom_same && left_and_right_same && top_value == left_value) {
|
||||
value = top_value;
|
||||
} else if (top_and_bottom_same && left_and_right_same) {
|
||||
value = StyleValueList::create(StyleValueVector { top_value, right_value }, StyleValueList::Separator::Space);
|
||||
} else if (left_and_right_same) {
|
||||
value = StyleValueList::create(StyleValueVector { top_value, right_value, bottom_value }, StyleValueList::Separator::Space);
|
||||
} else {
|
||||
value = StyleValueList::create(StyleValueVector { top_value, right_value, bottom_value, left_value }, StyleValueList::Separator::Space);
|
||||
}
|
||||
|
||||
return StyleProperty {
|
||||
.important = top->important,
|
||||
.property_id = property_id,
|
||||
.value = value.release_nonnull(),
|
||||
};
|
||||
}
|
||||
|
||||
// https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-getpropertyvalue
|
||||
Optional<StyleProperty> CSSStyleProperties::get_property_internal(PropertyID property_id) const
|
||||
{
|
||||
|
@ -488,41 +450,6 @@ Optional<StyleProperty> CSSStyleProperties::get_property_internal(PropertyID pro
|
|||
{ width->value, style->value, color->value })
|
||||
};
|
||||
}
|
||||
case PropertyID::BorderColor: {
|
||||
auto top = get_property_internal(PropertyID::BorderTopColor);
|
||||
auto right = get_property_internal(PropertyID::BorderRightColor);
|
||||
auto bottom = get_property_internal(PropertyID::BorderBottomColor);
|
||||
auto left = get_property_internal(PropertyID::BorderLeftColor);
|
||||
return style_property_for_sided_shorthand(property_id, top, right, bottom, left);
|
||||
}
|
||||
case PropertyID::BorderStyle: {
|
||||
auto top = get_property_internal(PropertyID::BorderTopStyle);
|
||||
auto right = get_property_internal(PropertyID::BorderRightStyle);
|
||||
auto bottom = get_property_internal(PropertyID::BorderBottomStyle);
|
||||
auto left = get_property_internal(PropertyID::BorderLeftStyle);
|
||||
return style_property_for_sided_shorthand(property_id, top, right, bottom, left);
|
||||
}
|
||||
case PropertyID::BorderWidth: {
|
||||
auto top = get_property_internal(PropertyID::BorderTopWidth);
|
||||
auto right = get_property_internal(PropertyID::BorderRightWidth);
|
||||
auto bottom = get_property_internal(PropertyID::BorderBottomWidth);
|
||||
auto left = get_property_internal(PropertyID::BorderLeftWidth);
|
||||
return style_property_for_sided_shorthand(property_id, top, right, bottom, left);
|
||||
}
|
||||
case PropertyID::Margin: {
|
||||
auto top = get_property_internal(PropertyID::MarginTop);
|
||||
auto right = get_property_internal(PropertyID::MarginRight);
|
||||
auto bottom = get_property_internal(PropertyID::MarginBottom);
|
||||
auto left = get_property_internal(PropertyID::MarginLeft);
|
||||
return style_property_for_sided_shorthand(property_id, top, right, bottom, left);
|
||||
}
|
||||
case PropertyID::Padding: {
|
||||
auto top = get_property_internal(PropertyID::PaddingTop);
|
||||
auto right = get_property_internal(PropertyID::PaddingRight);
|
||||
auto bottom = get_property_internal(PropertyID::PaddingBottom);
|
||||
auto left = get_property_internal(PropertyID::PaddingLeft);
|
||||
return style_property_for_sided_shorthand(property_id, top, right, bottom, left);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -711,6 +711,7 @@ Parser::ParseErrorOr<NonnullRefPtr<CSSStyleValue const>> Parser::parse_css_value
|
|||
if (auto parsed_value = parse_opacity_value(property_id, tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
return ParseError::SyntaxError;
|
||||
// FIXME: This can be removed once we have generic logic for parsing "positional-value-list-shorthand"s
|
||||
case PropertyID::Overflow:
|
||||
if (auto parsed_value = parse_overflow_value(tokens); parsed_value && !tokens.has_next_token())
|
||||
return parsed_value.release_nonnull();
|
||||
|
|
|
@ -638,6 +638,8 @@ void StyleComputer::for_each_property_expanding_shorthands(PropertyID property_i
|
|||
return;
|
||||
}
|
||||
|
||||
// FIXME: We should add logic in parse_css_value to parse "positional-value-list-shorthand"s as
|
||||
// ShorthandStyleValues to avoid the need for this (and assign_start_and_end_values).
|
||||
auto assign_edge_values = [&](PropertyID top_property, PropertyID right_property, PropertyID bottom_property, PropertyID left_property, CSSStyleValue const& value) {
|
||||
if (value.is_value_list()) {
|
||||
auto values = value.as_value_list().values();
|
||||
|
|
|
@ -68,6 +68,39 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
return ""_string;
|
||||
}
|
||||
|
||||
auto positional_value_list_shorthand_to_string = [&](Vector<ValueComparingNonnullRefPtr<CSSStyleValue const>> values) -> String {
|
||||
switch (values.size()) {
|
||||
case 2: {
|
||||
auto first_property_serialized = values[0]->to_string(mode);
|
||||
auto second_property_serialized = values[1]->to_string(mode);
|
||||
|
||||
if (first_property_serialized == second_property_serialized)
|
||||
return first_property_serialized;
|
||||
|
||||
return MUST(String::formatted("{} {}", first_property_serialized, second_property_serialized));
|
||||
}
|
||||
case 4: {
|
||||
auto first_property_serialized = values[0]->to_string(mode);
|
||||
auto second_property_serialized = values[1]->to_string(mode);
|
||||
auto third_property_serialized = values[2]->to_string(mode);
|
||||
auto fourth_property_serialized = values[3]->to_string(mode);
|
||||
|
||||
if (first_is_equal_to_all_of(first_property_serialized, second_property_serialized, third_property_serialized, fourth_property_serialized))
|
||||
return first_property_serialized;
|
||||
|
||||
if (first_property_serialized == third_property_serialized && second_property_serialized == fourth_property_serialized)
|
||||
return MUST(String::formatted("{} {}", first_property_serialized, second_property_serialized));
|
||||
|
||||
if (second_property_serialized == fourth_property_serialized)
|
||||
return MUST(String::formatted("{} {} {}", first_property_serialized, second_property_serialized, third_property_serialized));
|
||||
|
||||
return MUST(String::formatted("{} {} {} {}", first_property_serialized, second_property_serialized, third_property_serialized, fourth_property_serialized));
|
||||
}
|
||||
default:
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
};
|
||||
|
||||
auto default_to_string = [&]() {
|
||||
auto all_properties_same_value = true;
|
||||
auto first_property_value = m_properties.values.first();
|
||||
|
@ -368,13 +401,6 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
return "normal"_string;
|
||||
return MUST(String::join(' ', values));
|
||||
}
|
||||
case PropertyID::Gap: {
|
||||
auto row_gap = longhand(PropertyID::RowGap);
|
||||
auto column_gap = longhand(PropertyID::ColumnGap);
|
||||
if (row_gap == column_gap)
|
||||
return row_gap->to_string(mode);
|
||||
return MUST(String::formatted("{} {}", row_gap->to_string(mode), column_gap->to_string(mode)));
|
||||
}
|
||||
case PropertyID::GridArea: {
|
||||
auto& row_start = longhand(PropertyID::GridRowStart)->as_grid_track_placement();
|
||||
auto& column_start = longhand(PropertyID::GridColumnStart)->as_grid_track_placement();
|
||||
|
@ -442,35 +468,10 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
return start->to_string(mode);
|
||||
return MUST(String::formatted("{} / {}", start->to_string(mode), end->to_string(mode)));
|
||||
}
|
||||
case PropertyID::Overflow: {
|
||||
auto overflow_x = longhand(PropertyID::OverflowX);
|
||||
auto overflow_y = longhand(PropertyID::OverflowY);
|
||||
if (overflow_x == overflow_y)
|
||||
return overflow_x->to_string(mode);
|
||||
|
||||
return MUST(String::formatted("{} {}", overflow_x->to_string(mode), overflow_y->to_string(mode)));
|
||||
}
|
||||
case PropertyID::PlaceContent: {
|
||||
auto align_content = longhand(PropertyID::AlignContent)->to_string(mode);
|
||||
auto justify_content = longhand(PropertyID::JustifyContent)->to_string(mode);
|
||||
if (align_content == justify_content)
|
||||
return align_content;
|
||||
return MUST(String::formatted("{} {}", align_content, justify_content));
|
||||
}
|
||||
case PropertyID::PlaceItems: {
|
||||
auto align_items = longhand(PropertyID::AlignItems)->to_string(mode);
|
||||
auto justify_items = longhand(PropertyID::JustifyItems)->to_string(mode);
|
||||
if (align_items == justify_items)
|
||||
return align_items;
|
||||
return MUST(String::formatted("{} {}", align_items, justify_items));
|
||||
}
|
||||
case PropertyID::PlaceSelf: {
|
||||
auto align_self = longhand(PropertyID::AlignSelf)->to_string(mode);
|
||||
auto justify_self = longhand(PropertyID::JustifySelf)->to_string(mode);
|
||||
if (align_self == justify_self)
|
||||
return align_self;
|
||||
return MUST(String::formatted("{} {}", align_self, justify_self));
|
||||
}
|
||||
case PropertyID::PlaceContent:
|
||||
case PropertyID::PlaceItems:
|
||||
case PropertyID::PlaceSelf:
|
||||
return positional_value_list_shorthand_to_string(m_properties.values);
|
||||
case PropertyID::TextDecoration: {
|
||||
// The rule here seems to be, only print what's different from the default value,
|
||||
// but if they're all default, print the line.
|
||||
|
@ -521,6 +522,9 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const
|
|||
return default_to_string();
|
||||
}
|
||||
default:
|
||||
if (property_is_positional_value_list_shorthand(m_properties.shorthand_property))
|
||||
return positional_value_list_shorthand_to_string(m_properties.values);
|
||||
|
||||
return default_to_string();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 10 tests
|
||||
|
||||
9 Pass
|
||||
1 Fail
|
||||
10 Pass
|
||||
Pass e.style['border-block-start-width'] = "10px" should set the property value
|
||||
Pass e.style['border-block-start-width'] = "calc(10px + 0.5em)" should set the property value
|
||||
Pass e.style['border-block-start-width'] = "thick" should set the property value
|
||||
|
@ -12,5 +11,5 @@ Pass e.style['border-block-end-width'] = "0" should set the property value
|
|||
Pass e.style['border-block-end-width'] = "calc(10px - 0.5em)" should set the property value
|
||||
Pass e.style['border-block-end-width'] = "medium" should set the property value
|
||||
Pass e.style['border-block-width'] = "10px" should set the property value
|
||||
Fail e.style['border-block-width'] = "medium calc(10px + 0.5em)" should set the property value
|
||||
Pass e.style['border-block-width'] = "medium calc(10px + 0.5em)" should set the property value
|
||||
Pass e.style['border-block-width'] = "10px 10px" should set the property value
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 10 tests
|
||||
|
||||
9 Pass
|
||||
1 Fail
|
||||
10 Pass
|
||||
Pass e.style['border-inline-start-width'] = "10px" should set the property value
|
||||
Pass e.style['border-inline-start-width'] = "calc(10px + 0.5em)" should set the property value
|
||||
Pass e.style['border-inline-start-width'] = "thick" should set the property value
|
||||
|
@ -12,5 +11,5 @@ Pass e.style['border-inline-end-width'] = "0" should set the property value
|
|||
Pass e.style['border-inline-end-width'] = "calc(10px - 0.5em)" should set the property value
|
||||
Pass e.style['border-inline-end-width'] = "medium" should set the property value
|
||||
Pass e.style['border-inline-width'] = "10px" should set the property value
|
||||
Fail e.style['border-inline-width'] = "medium calc(10px + 0.5em)" should set the property value
|
||||
Pass e.style['border-inline-width'] = "medium calc(10px + 0.5em)" should set the property value
|
||||
Pass e.style['border-inline-width'] = "10px 10px" should set the property value
|
|
@ -0,0 +1,18 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 12 tests
|
||||
|
||||
8 Pass
|
||||
4 Fail
|
||||
Pass Property inset-block-start value 'auto'
|
||||
Pass Property inset-block-end value '-10px'
|
||||
Pass Property inset-inline-start value '-20%'
|
||||
Fail Property inset-inline-end value 'calc(10px - 0.5em)'
|
||||
Pass Property inset-block value 'auto'
|
||||
Pass Property inset-block value '-10px'
|
||||
Fail Property inset-block value 'calc(10px - 0.5em) -20%'
|
||||
Pass Property inset-block value 'auto auto'
|
||||
Pass Property inset-inline value '-20%'
|
||||
Fail Property inset-inline value 'calc(10px - 0.5em)'
|
||||
Pass Property inset-inline value '-10px auto'
|
||||
Fail Property inset-inline value 'auto calc(10px + 0.5em)'
|
|
@ -0,0 +1,17 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 12 tests
|
||||
|
||||
12 Pass
|
||||
Pass e.style['inset-block-start'] = "auto" should set the property value
|
||||
Pass e.style['inset-block-end'] = "-10px" should set the property value
|
||||
Pass e.style['inset-inline-start'] = "-20%" should set the property value
|
||||
Pass e.style['inset-inline-end'] = "calc(10px - 0.5em)" should set the property value
|
||||
Pass e.style['inset-block'] = "auto" should set the property value
|
||||
Pass e.style['inset-block'] = "-10px" should set the property value
|
||||
Pass e.style['inset-block'] = "calc(10px - 0.5em) -20%" should set the property value
|
||||
Pass e.style['inset-block'] = "auto auto" should set the property value
|
||||
Pass e.style['inset-inline'] = "-20%" should set the property value
|
||||
Pass e.style['inset-inline'] = "calc(10px - 0.5em)" should set the property value
|
||||
Pass e.style['inset-inline'] = "-10px auto" should set the property value
|
||||
Pass e.style['inset-inline'] = "auto calc(10px + 0.5em)" should set the property value
|
|
@ -0,0 +1,14 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 8 tests
|
||||
|
||||
6 Pass
|
||||
2 Fail
|
||||
Pass Property inset value 'auto'
|
||||
Pass Property inset value '-10px'
|
||||
Fail Property inset value 'calc(10px - 0.5em) -20%'
|
||||
Pass Property inset value 'auto auto'
|
||||
Fail Property inset value '10px calc(10px - 0.5em) -30px'
|
||||
Pass Property inset value 'auto auto auto'
|
||||
Pass Property inset value '10px 20px auto -30px'
|
||||
Pass Property inset value 'auto auto auto auto'
|
|
@ -0,0 +1,13 @@
|
|||
Harness status: OK
|
||||
|
||||
Found 8 tests
|
||||
|
||||
8 Pass
|
||||
Pass e.style['inset'] = "auto" should set the property value
|
||||
Pass e.style['inset'] = "-10px" should set the property value
|
||||
Pass e.style['inset'] = "calc(-0.5em + 10px) -20%" should set the property value
|
||||
Pass e.style['inset'] = "auto auto" should set the property value
|
||||
Pass e.style['inset'] = "10px calc(-0.5em + 10px) -30px" should set the property value
|
||||
Pass e.style['inset'] = "auto auto auto" should set the property value
|
||||
Pass e.style['inset'] = "10px calc(-0.5em + 10px) auto -30px" should set the property value
|
||||
Pass e.style['inset'] = "auto auto auto auto" should set the property value
|
|
@ -0,0 +1,35 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Logical Properties and Values: getComputedStyle().insetBlock / insetInline</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-inset-block">
|
||||
<meta name="assert" content="Computed value is as specified, with lengths made absolute.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/computed-testcommon.js"></script>
|
||||
<style>
|
||||
#target {
|
||||
font-size: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_computed_value("inset-block-start", "auto");
|
||||
test_computed_value("inset-block-end", "-10px");
|
||||
test_computed_value("inset-inline-start", "-20%");
|
||||
test_computed_value("inset-inline-end", "calc(10px - 0.5em)", "-10px");
|
||||
|
||||
test_computed_value("inset-block", "auto");
|
||||
test_computed_value("inset-block", "-10px");
|
||||
test_computed_value("inset-block", "calc(10px - 0.5em) -20%", "-10px -20%");
|
||||
test_computed_value("inset-block", "auto auto", "auto");
|
||||
test_computed_value("inset-inline", "-20%");
|
||||
test_computed_value("inset-inline", "calc(10px - 0.5em)", "-10px");
|
||||
test_computed_value("inset-inline", "-10px auto");
|
||||
test_computed_value("inset-inline", "auto calc(10px + 0.5em)", "auto 30px");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,30 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Logical Properties and Values: parsing inset-block and inset-inline with valid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-inset-block">
|
||||
<meta name="assert" content="inset-block, inset-inline support the full grammar '<'top'>{1,2}'.">
|
||||
<meta name="assert" content="inset-block, inset-inline longhands support the full grammar '<'top'>'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_valid_value("inset-block-start", "auto");
|
||||
test_valid_value("inset-block-end", "-10px");
|
||||
test_valid_value("inset-inline-start", "-20%");
|
||||
test_valid_value("inset-inline-end", "calc(10px - 0.5em)", "calc(-0.5em + 10px)");
|
||||
|
||||
test_valid_value("inset-block", "auto");
|
||||
test_valid_value("inset-block", "-10px");
|
||||
test_valid_value("inset-block", "calc(10px - 0.5em) -20%", "calc(-0.5em + 10px) -20%");
|
||||
test_valid_value("inset-block", "auto auto", "auto");
|
||||
test_valid_value("inset-inline", "-20%");
|
||||
test_valid_value("inset-inline", "calc(10px - 0.5em)", "calc(-0.5em + 10px)");
|
||||
test_valid_value("inset-inline", "-10px auto");
|
||||
test_valid_value("inset-inline", "auto calc(10px + 0.5em)", "auto calc(0.5em + 10px)");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,33 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Logical Properties and Values: getComputedStyle().inset</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-inset">
|
||||
<meta name="assert" content="Computed value is as specified, with lengths made absolute.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/computed-testcommon.js"></script>
|
||||
<style>
|
||||
#target {
|
||||
font-size: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div id="target"></div>
|
||||
<script>
|
||||
test_computed_value("inset", "auto");
|
||||
test_computed_value("inset", "-10px");
|
||||
|
||||
test_computed_value("inset", "calc(10px - 0.5em) -20%", "-10px -20%");
|
||||
test_computed_value("inset", "auto auto", "auto");
|
||||
|
||||
test_computed_value("inset", "10px calc(10px - 0.5em) -30px", "10px -10px -30px");
|
||||
test_computed_value("inset", "auto auto auto", "auto");
|
||||
|
||||
test_computed_value("inset", "10px 20px auto -30px");
|
||||
test_computed_value("inset", "auto auto auto auto", "auto");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS Logical Properties and Values: parsing inset with valid values</title>
|
||||
<link rel="help" href="https://drafts.csswg.org/css-logical/#propdef-inset">
|
||||
<meta name="assert" content="inset supports the full grammar '<'top'>{1,4}'.">
|
||||
<script src="../../../resources/testharness.js"></script>
|
||||
<script src="../../../resources/testharnessreport.js"></script>
|
||||
<script src="../../../css/support/parsing-testcommon.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
test_valid_value("inset", "auto");
|
||||
test_valid_value("inset", "-10px");
|
||||
|
||||
test_valid_value("inset", "calc(-0.5em + 10px) -20%");
|
||||
test_valid_value("inset", "auto auto", "auto");
|
||||
|
||||
test_valid_value("inset", "10px calc(-0.5em + 10px) -30px");
|
||||
test_valid_value("inset", "auto auto auto", "auto");
|
||||
|
||||
test_valid_value("inset", "10px calc(-0.5em + 10px) auto -30px");
|
||||
test_valid_value("inset", "auto auto auto auto", "auto");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Loading…
Add table
Add a link
Reference in a new issue