diff --git a/Tests/LibWeb/Layout/expected/grid/place-items-center.txt b/Tests/LibWeb/Layout/expected/grid/place-items-center.txt new file mode 100644 index 0000000000..2259da2898 --- /dev/null +++ b/Tests/LibWeb/Layout/expected/grid/place-items-center.txt @@ -0,0 +1,8 @@ +Viewport <#document> at (0,0) content-size 800x600 children: not-inline + BlockContainer at (1,1) content-size 798x37.46875 [BFC] children: not-inline + Box at (10,10) content-size 780x19.46875 [GFC] children: not-inline + BlockContainer
at (362.9375,11) content-size 74.125x17.46875 [BFC] children: inline + line 0 width: 74.125, height: 17.46875, bottom: 17.46875, baseline: 13.53125 + frag 0 from TextNode start: 0, length: 8, rect: [362.9375,11 74.125x17.46875] + "Download" + TextNode <#text> diff --git a/Tests/LibWeb/Layout/input/grid/place-items-center.html b/Tests/LibWeb/Layout/input/grid/place-items-center.html new file mode 100644 index 0000000000..6984595cb3 --- /dev/null +++ b/Tests/LibWeb/Layout/input/grid/place-items-center.html @@ -0,0 +1,9 @@ +
Download \ No newline at end of file diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 2ca8ccccf3..107dccccfe 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -110,6 +110,7 @@ set(SOURCES CSS/StyleValues/NumberStyleValue.cpp CSS/StyleValues/OverflowStyleValue.cpp CSS/StyleValues/PlaceContentStyleValue.cpp + CSS/StyleValues/PlaceItemsStyleValue.cpp CSS/StyleValues/PositionStyleValue.cpp CSS/StyleValues/RadialGradientStyleValue.cpp CSS/StyleValues/RectStyleValue.cpp diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index a974ddc543..bfea495df3 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -70,6 +70,7 @@ #include #include #include +#include #include #include #include @@ -6222,6 +6223,25 @@ ErrorOr> Parser::parse_place_content_value(Vector> Parser::parse_place_items_value(Vector const& component_values) +{ + auto tokens = TokenStream { component_values }; + auto maybe_align_items_value = TRY(parse_css_value_for_property(PropertyID::AlignItems, tokens)); + if (!maybe_align_items_value) + return nullptr; + + if (component_values.size() == 1) { + if (!property_accepts_identifier(PropertyID::JustifyItems, maybe_align_items_value->to_identifier())) + return nullptr; + return PlaceItemsStyleValue::create(*maybe_align_items_value, *maybe_align_items_value); + } + + auto maybe_justify_items_value = TRY(parse_css_value_for_property(PropertyID::JustifyItems, tokens)); + if (!maybe_justify_items_value) + return nullptr; + return PlaceItemsStyleValue::create(*maybe_align_items_value, *maybe_justify_items_value); +} + ErrorOr> Parser::parse_text_decoration_value(Vector const& component_values) { RefPtr decoration_line; @@ -7456,6 +7476,10 @@ Parser::ParseErrorOr> Parser::parse_css_value(Property if (auto parsed_value = FIXME_TRY(parse_place_content_value(component_values))) return parsed_value.release_nonnull(); return ParseError::SyntaxError; + case PropertyID::PlaceItems: + if (auto parsed_value = FIXME_TRY(parse_place_items_value(component_values))) + return parsed_value.release_nonnull(); + return ParseError::SyntaxError; case PropertyID::TextDecoration: if (auto parsed_value = FIXME_TRY(parse_text_decoration_value(component_values))) return parsed_value.release_nonnull(); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index ee015dc657..75c17a6749 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -326,6 +326,7 @@ private: ErrorOr> parse_list_style_value(Vector const&); ErrorOr> parse_overflow_value(Vector const&); ErrorOr> parse_place_content_value(Vector const&); + ErrorOr> parse_place_items_value(Vector const&); enum class AllowInsetKeyword { No, Yes, diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index 979a47c8c8..906a725f1f 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -1765,6 +1765,14 @@ "justify-content" ] }, + "place-items": { + "inherited": false, + "initial": "normal", + "longhands": [ + "align-items", + "justify-items" + ] + }, "pointer-events": { "affects-layout": false, "inherited": true, diff --git a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp index da74165e57..0733ddfd25 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleComputer.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -432,6 +433,19 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope return; } + if (property_id == CSS::PropertyID::PlaceItems) { + if (value.is_place_items()) { + auto const& place_items = value.as_place_items(); + style.set_property(CSS::PropertyID::AlignItems, place_items.align_items()); + style.set_property(CSS::PropertyID::JustifyItems, place_items.justify_items()); + return; + } + + style.set_property(CSS::PropertyID::AlignItems, value); + style.set_property(CSS::PropertyID::JustifyItems, value); + return; + } + if (property_id == CSS::PropertyID::Border) { set_property_expanding_shorthands(style, CSS::PropertyID::BorderTop, value, document, declaration); set_property_expanding_shorthands(style, CSS::PropertyID::BorderRight, value, document, declaration); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 9818569c64..64849832ff 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -50,6 +50,7 @@ #include #include #include +#include #include #include #include @@ -318,6 +319,12 @@ PlaceContentStyleValue const& StyleValue::as_place_content() const return static_cast(*this); } +PlaceItemsStyleValue const& StyleValue::as_place_items() const +{ + VERIFY(is_place_items()); + return static_cast(*this); +} + PositionStyleValue const& StyleValue::as_position() const { VERIFY(is_position()); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 513dfa2f5e..35df819887 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -126,6 +126,7 @@ public: Overflow, Percentage, PlaceContent, + PlaceItems, Position, RadialGradient, Ratio, @@ -184,6 +185,7 @@ public: bool is_overflow() const { return type() == Type::Overflow; } bool is_percentage() const { return type() == Type::Percentage; } bool is_place_content() const { return type() == Type::PlaceContent; } + bool is_place_items() const { return type() == Type::PlaceItems; } bool is_position() const { return type() == Type::Position; } bool is_radial_gradient() const { return type() == Type::RadialGradient; } bool is_ratio() const { return type() == Type::Ratio; } @@ -241,6 +243,7 @@ public: OverflowStyleValue const& as_overflow() const; PercentageStyleValue const& as_percentage() const; PlaceContentStyleValue const& as_place_content() const; + PlaceItemsStyleValue const& as_place_items() const; PositionStyleValue const& as_position() const; RadialGradientStyleValue const& as_radial_gradient() const; RatioStyleValue const& as_ratio() const; @@ -295,6 +298,7 @@ public: OverflowStyleValue& as_overflow() { return const_cast(const_cast(*this).as_overflow()); } PercentageStyleValue& as_percentage() { return const_cast(const_cast(*this).as_percentage()); } PlaceContentStyleValue& as_place_content() { return const_cast(const_cast(*this).as_place_content()); } + PlaceItemsStyleValue& as_place_items() { return const_cast(const_cast(*this).as_place_items()); } PositionStyleValue& as_position() { return const_cast(const_cast(*this).as_position()); } RadialGradientStyleValue& as_radial_gradient() { return const_cast(const_cast(*this).as_radial_gradient()); } RatioStyleValue& as_ratio() { return const_cast(const_cast(*this).as_ratio()); } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.cpp new file mode 100644 index 0000000000..efe0187bea --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "PlaceItemsStyleValue.h" + +namespace Web::CSS { + +ErrorOr PlaceItemsStyleValue::to_string() const +{ + return String::formatted("{} {}", TRY(m_properties.align_items->to_string()), TRY(m_properties.justify_items->to_string())); +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.h new file mode 100644 index 0000000000..1a0e9ac627 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2023, Aliaksandr Kalenik + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include + +namespace Web::CSS { + +class PlaceItemsStyleValue final : public StyleValueWithDefaultOperators { +public: + static ErrorOr> create(ValueComparingNonnullRefPtr align_items, ValueComparingNonnullRefPtr justify_items) + { + return adopt_nonnull_ref_or_enomem(new (nothrow) PlaceItemsStyleValue(move(align_items), move(justify_items))); + } + virtual ~PlaceItemsStyleValue() override = default; + + ValueComparingNonnullRefPtr align_items() const { return m_properties.align_items; } + ValueComparingNonnullRefPtr justify_items() const { return m_properties.justify_items; } + + virtual ErrorOr to_string() const override; + + bool properties_equal(PlaceItemsStyleValue const& other) const { return m_properties == other.m_properties; } + +private: + PlaceItemsStyleValue(ValueComparingNonnullRefPtr align_items, ValueComparingNonnullRefPtr justify_items) + : StyleValueWithDefaultOperators(Type::PlaceItems) + , m_properties { .align_items = move(align_items), .justify_items = move(justify_items) } + { + } + + struct Properties { + ValueComparingNonnullRefPtr align_items; + ValueComparingNonnullRefPtr justify_items; + bool operator==(Properties const&) const = default; + } m_properties; +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 80fc0ff4ee..a79bb1be43 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -146,6 +146,7 @@ class Percentage; class PercentageOrCalculated; class PercentageStyleValue; class PlaceContentStyleValue; +class PlaceItemsStyleValue; class PositionStyleValue; class PropertyOwningCSSStyleDeclaration; class RadialGradientStyleValue;