diff --git a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp index bf56e1a3dd8..194031705a6 100644 --- a/Libraries/LibWeb/CSS/CSSStyleProperties.cpp +++ b/Libraries/LibWeb/CSS/CSSStyleProperties.cpp @@ -425,44 +425,6 @@ StringView CSSStyleProperties::get_property_priority(StringView property_name) c return maybe_property->important == Important::Yes ? "important"sv : ""sv; } -static Optional style_property_for_sided_shorthand(PropertyID property_id, Optional const& top, Optional const& right, Optional const& bottom, Optional 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 const top_value { top->value }; - ValueComparingNonnullRefPtr const right_value { right->value }; - ValueComparingNonnullRefPtr const bottom_value { bottom->value }; - ValueComparingNonnullRefPtr 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 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 CSSStyleProperties::get_property_internal(PropertyID property_id) const { @@ -488,41 +450,6 @@ Optional 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; } diff --git a/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp b/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp index eff705585b3..3d34b152837 100644 --- a/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp +++ b/Libraries/LibWeb/CSS/Parser/PropertyParsing.cpp @@ -711,6 +711,7 @@ Parser::ParseErrorOr> 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(); diff --git a/Libraries/LibWeb/CSS/StyleComputer.cpp b/Libraries/LibWeb/CSS/StyleComputer.cpp index 1328e569f01..06e383caf01 100644 --- a/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -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(); diff --git a/Libraries/LibWeb/CSS/StyleValues/ShorthandStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/ShorthandStyleValue.cpp index 60e745b8325..fdd6601fdc1 100644 --- a/Libraries/LibWeb/CSS/StyleValues/ShorthandStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/ShorthandStyleValue.cpp @@ -68,6 +68,39 @@ String ShorthandStyleValue::to_string(SerializationMode mode) const return ""_string; } + auto positional_value_list_shorthand_to_string = [&](Vector> 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(); } } diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-block-width-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-block-width-valid.txt index 51616311063..d7f4eb1171f 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-block-width-valid.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-block-width-valid.txt @@ -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 \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-inline-width-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-inline-width-valid.txt index 17d10a1727a..91483f8b88e 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-inline-width-valid.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/border-inline-width-valid.txt @@ -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 \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-block-inline-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-block-inline-computed.txt new file mode 100644 index 00000000000..fbd021d937b --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-block-inline-computed.txt @@ -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)' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-block-inline-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-block-inline-valid.txt new file mode 100644 index 00000000000..6c91ee9c388 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-block-inline-valid.txt @@ -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 \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-computed.txt new file mode 100644 index 00000000000..e801569598e --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-computed.txt @@ -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' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-valid.txt new file mode 100644 index 00000000000..b40834f1f30 --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-logical/parsing/inset-valid.txt @@ -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 \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-block-inline-computed.html b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-block-inline-computed.html new file mode 100644 index 00000000000..2dfa96712c1 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-block-inline-computed.html @@ -0,0 +1,35 @@ + + + + +CSS Logical Properties and Values: getComputedStyle().insetBlock / insetInline + + + + + + + + +
+ + + diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-block-inline-valid.html b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-block-inline-valid.html new file mode 100644 index 00000000000..6159ca1f47e --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-block-inline-valid.html @@ -0,0 +1,30 @@ + + + + +CSS Logical Properties and Values: parsing inset-block and inset-inline with valid values + + + + + + + + + + + diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-computed.html b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-computed.html new file mode 100644 index 00000000000..de264f1a42e --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-computed.html @@ -0,0 +1,33 @@ + + + + +CSS Logical Properties and Values: getComputedStyle().inset + + + + + + + + +
+ + + diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-valid.html b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-valid.html new file mode 100644 index 00000000000..fad1fd0568c --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-logical/parsing/inset-valid.html @@ -0,0 +1,27 @@ + + + + +CSS Logical Properties and Values: parsing inset with valid values + + + + + + + + + +