فهرست منبع

LibWeb: Add support for "place-items" CSS property

Adds support for place-items property which allows to specify both
align-items and justify-items in a single declaration.
Aliaksandr Kalenik 2 سال پیش
والد
کامیت
a8587fe54e

+ 8 - 0
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 <html> at (1,1) content-size 798x37.46875 [BFC] children: not-inline
+    Box <body> at (10,10) content-size 780x19.46875 [GFC] children: not-inline
+      BlockContainer <div> 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>

+ 9 - 0
Tests/LibWeb/Layout/input/grid/place-items-center.html

@@ -0,0 +1,9 @@
+<!DOCTYPE html><style>    
+    * {
+        border: 1px solid black;    
+    }
+    body {
+        display: grid;
+        place-items: center;
+    }
+</style><body><div>Download

+ 1 - 0
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

+ 24 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

@@ -70,6 +70,7 @@
 #include <LibWeb/CSS/StyleValues/OverflowStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PlaceContentStyleValue.h>
+#include <LibWeb/CSS/StyleValues/PlaceItemsStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
 #include <LibWeb/CSS/StyleValues/RadialGradientStyleValue.h>
 #include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
@@ -6222,6 +6223,25 @@ ErrorOr<RefPtr<StyleValue>> Parser::parse_place_content_value(Vector<ComponentVa
     return PlaceContentStyleValue::create(maybe_align_content_value.release_nonnull(), maybe_justify_content_value.release_nonnull());
 }
 
+ErrorOr<RefPtr<StyleValue>> Parser::parse_place_items_value(Vector<ComponentValue> 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<RefPtr<StyleValue>> Parser::parse_text_decoration_value(Vector<ComponentValue> const& component_values)
 {
     RefPtr<StyleValue> decoration_line;
@@ -7456,6 +7476,10 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> 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();

+ 1 - 0
Userland/Libraries/LibWeb/CSS/Parser/Parser.h

@@ -326,6 +326,7 @@ private:
     ErrorOr<RefPtr<StyleValue>> parse_list_style_value(Vector<ComponentValue> const&);
     ErrorOr<RefPtr<StyleValue>> parse_overflow_value(Vector<ComponentValue> const&);
     ErrorOr<RefPtr<StyleValue>> parse_place_content_value(Vector<ComponentValue> const&);
+    ErrorOr<RefPtr<StyleValue>> parse_place_items_value(Vector<ComponentValue> const&);
     enum class AllowInsetKeyword {
         No,
         Yes,

+ 8 - 0
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,

+ 14 - 0
Userland/Libraries/LibWeb/CSS/StyleComputer.cpp

@@ -54,6 +54,7 @@
 #include <LibWeb/CSS/StyleValues/OverflowStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PlaceContentStyleValue.h>
+#include <LibWeb/CSS/StyleValues/PlaceItemsStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
 #include <LibWeb/CSS/StyleValues/RectStyleValue.h>
 #include <LibWeb/CSS/StyleValues/StyleValueList.h>
@@ -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);

+ 7 - 0
Userland/Libraries/LibWeb/CSS/StyleValue.cpp

@@ -50,6 +50,7 @@
 #include <LibWeb/CSS/StyleValues/OverflowStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PlaceContentStyleValue.h>
+#include <LibWeb/CSS/StyleValues/PlaceItemsStyleValue.h>
 #include <LibWeb/CSS/StyleValues/PositionStyleValue.h>
 #include <LibWeb/CSS/StyleValues/RadialGradientStyleValue.h>
 #include <LibWeb/CSS/StyleValues/RatioStyleValue.h>
@@ -318,6 +319,12 @@ PlaceContentStyleValue const& StyleValue::as_place_content() const
     return static_cast<PlaceContentStyleValue const&>(*this);
 }
 
+PlaceItemsStyleValue const& StyleValue::as_place_items() const
+{
+    VERIFY(is_place_items());
+    return static_cast<PlaceItemsStyleValue const&>(*this);
+}
+
 PositionStyleValue const& StyleValue::as_position() const
 {
     VERIFY(is_position());

+ 4 - 0
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<OverflowStyleValue&>(const_cast<StyleValue const&>(*this).as_overflow()); }
     PercentageStyleValue& as_percentage() { return const_cast<PercentageStyleValue&>(const_cast<StyleValue const&>(*this).as_percentage()); }
     PlaceContentStyleValue& as_place_content() { return const_cast<PlaceContentStyleValue&>(const_cast<StyleValue const&>(*this).as_place_content()); }
+    PlaceItemsStyleValue& as_place_items() { return const_cast<PlaceItemsStyleValue&>(const_cast<StyleValue const&>(*this).as_place_items()); }
     PositionStyleValue& as_position() { return const_cast<PositionStyleValue&>(const_cast<StyleValue const&>(*this).as_position()); }
     RadialGradientStyleValue& as_radial_gradient() { return const_cast<RadialGradientStyleValue&>(const_cast<StyleValue const&>(*this).as_radial_gradient()); }
     RatioStyleValue& as_ratio() { return const_cast<RatioStyleValue&>(const_cast<StyleValue const&>(*this).as_ratio()); }

+ 16 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.cpp

@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#include "PlaceItemsStyleValue.h"
+
+namespace Web::CSS {
+
+ErrorOr<String> PlaceItemsStyleValue::to_string() const
+{
+    return String::formatted("{} {}", TRY(m_properties.align_items->to_string()), TRY(m_properties.justify_items->to_string()));
+}
+
+}

+ 42 - 0
Userland/Libraries/LibWeb/CSS/StyleValues/PlaceItemsStyleValue.h

@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2023, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <LibWeb/CSS/StyleValue.h>
+
+namespace Web::CSS {
+
+class PlaceItemsStyleValue final : public StyleValueWithDefaultOperators<PlaceItemsStyleValue> {
+public:
+    static ErrorOr<ValueComparingNonnullRefPtr<PlaceItemsStyleValue>> create(ValueComparingNonnullRefPtr<StyleValue> align_items, ValueComparingNonnullRefPtr<StyleValue> justify_items)
+    {
+        return adopt_nonnull_ref_or_enomem(new (nothrow) PlaceItemsStyleValue(move(align_items), move(justify_items)));
+    }
+    virtual ~PlaceItemsStyleValue() override = default;
+
+    ValueComparingNonnullRefPtr<StyleValue> align_items() const { return m_properties.align_items; }
+    ValueComparingNonnullRefPtr<StyleValue> justify_items() const { return m_properties.justify_items; }
+
+    virtual ErrorOr<String> to_string() const override;
+
+    bool properties_equal(PlaceItemsStyleValue const& other) const { return m_properties == other.m_properties; }
+
+private:
+    PlaceItemsStyleValue(ValueComparingNonnullRefPtr<StyleValue> align_items, ValueComparingNonnullRefPtr<StyleValue> justify_items)
+        : StyleValueWithDefaultOperators(Type::PlaceItems)
+        , m_properties { .align_items = move(align_items), .justify_items = move(justify_items) }
+    {
+    }
+
+    struct Properties {
+        ValueComparingNonnullRefPtr<StyleValue> align_items;
+        ValueComparingNonnullRefPtr<StyleValue> justify_items;
+        bool operator==(Properties const&) const = default;
+    } m_properties;
+};
+
+}

+ 1 - 0
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;