LibWeb: Add support for parsing grid-auto-flow CSS property

Co-Authored-By: Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
This commit is contained in:
Andreas Kling 2023-08-17 20:25:18 +02:00 committed by Alexander Kalenik
parent 1a5533e528
commit 703c2bb06e
Notes: sideshowbarker 2024-07-17 16:23:55 +09:00
13 changed files with 168 additions and 0 deletions

View file

@ -99,6 +99,7 @@ set(SOURCES
CSS/StyleValues/FlexStyleValue.cpp
CSS/StyleValues/FontStyleValue.cpp
CSS/StyleValues/GridAreaShorthandStyleValue.cpp
CSS/StyleValues/GridAutoFlowStyleValue.cpp
CSS/StyleValues/GridTemplateAreaStyleValue.cpp
CSS/StyleValues/GridTrackPlacementStyleValue.cpp
CSS/StyleValues/GridTrackPlacementShorthandStyleValue.cpp

View file

@ -32,6 +32,11 @@ struct AspectRatio {
Optional<Ratio> preferred_ratio;
};
struct GridAutoFlow {
bool row { true };
bool dense { false };
};
class InitialValues {
public:
static AspectRatio aspect_ratio() { return AspectRatio { true, {} }; }
@ -101,6 +106,7 @@ public:
static CSS::GridTrackPlacement grid_column_start() { return CSS::GridTrackPlacement::make_auto(); }
static CSS::GridTrackPlacement grid_row_end() { return CSS::GridTrackPlacement::make_auto(); }
static CSS::GridTrackPlacement grid_row_start() { return CSS::GridTrackPlacement::make_auto(); }
static CSS::GridAutoFlow grid_auto_flow() { return CSS::GridAutoFlow {}; }
static CSS::Size column_gap() { return CSS::Size::make_auto(); }
static CSS::Size row_gap() { return CSS::Size::make_auto(); }
static CSS::BorderCollapse border_collapse() { return CSS::BorderCollapse::Separate; }
@ -276,6 +282,7 @@ public:
Variant<CSS::VerticalAlign, CSS::LengthPercentage> const& vertical_align() const { return m_noninherited.vertical_align; }
CSS::GridTrackSizeList const& grid_auto_columns() const { return m_noninherited.grid_auto_columns; }
CSS::GridTrackSizeList const& grid_auto_rows() const { return m_noninherited.grid_auto_rows; }
CSS::GridAutoFlow const& grid_auto_flow() const { return m_noninherited.grid_auto_flow; }
CSS::GridTrackSizeList const& grid_template_columns() const { return m_noninherited.grid_template_columns; }
CSS::GridTrackSizeList const& grid_template_rows() const { return m_noninherited.grid_template_rows; }
CSS::GridTrackPlacement const& grid_column_end() const { return m_noninherited.grid_column_end; }
@ -436,6 +443,7 @@ protected:
CSS::GridTrackSizeList grid_auto_rows;
CSS::GridTrackSizeList grid_template_columns;
CSS::GridTrackSizeList grid_template_rows;
CSS::GridAutoFlow grid_auto_flow { InitialValues::grid_auto_flow() };
CSS::GridTrackPlacement grid_column_end { InitialValues::grid_column_end() };
CSS::GridTrackPlacement grid_column_start { InitialValues::grid_column_start() };
CSS::GridTrackPlacement grid_row_end { InitialValues::grid_row_end() };
@ -549,6 +557,7 @@ public:
void set_row_gap(CSS::Size const& row_gap) { m_noninherited.row_gap = row_gap; }
void set_border_collapse(CSS::BorderCollapse const& border_collapse) { m_inherited.border_collapse = border_collapse; }
void set_grid_template_areas(Vector<Vector<String>> const& grid_template_areas) { m_noninherited.grid_template_areas = grid_template_areas; }
void set_grid_auto_flow(CSS::GridAutoFlow grid_auto_flow) { m_noninherited.grid_auto_flow = grid_auto_flow; }
void set_transition_delay(CSS::Time const& transition_delay) { m_noninherited.transition_delay = transition_delay; }
void set_table_layout(CSS::TableLayout value) { m_noninherited.table_layout = value; }

View file

@ -53,6 +53,7 @@
#include <LibWeb/CSS/StyleValues/FontStyleValue.h>
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAreaShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
@ -5308,6 +5309,57 @@ RefPtr<StyleValue> Parser::parse_grid_track_size_list(Vector<ComponentValue> con
return GridTrackSizeListStyleValue::create(CSS::GridTrackSizeList(track_list, line_names_list));
}
// https://www.w3.org/TR/css-grid-1/#grid-auto-flow-property
RefPtr<GridAutoFlowStyleValue> Parser::parse_grid_auto_flow_value(Vector<ComponentValue> const& component_values)
{
// [ row | column ] || dense
TokenStream<ComponentValue> tokens { component_values };
if (!tokens.has_next_token())
return nullptr;
auto parse_axis = [&]() -> Optional<GridAutoFlowStyleValue::Axis> {
auto transaction = tokens.begin_transaction();
auto token = tokens.next_token();
if (!token.is(Token::Type::Ident))
return {};
auto const& ident = token.token().ident();
if (ident.equals_ignoring_ascii_case("row"sv)) {
transaction.commit();
return GridAutoFlowStyleValue::Axis::Row;
} else if (ident.equals_ignoring_ascii_case("column"sv)) {
transaction.commit();
return GridAutoFlowStyleValue::Axis::Column;
}
return {};
};
auto parse_dense = [&]() -> Optional<GridAutoFlowStyleValue::Dense> {
auto transaction = tokens.begin_transaction();
auto token = tokens.next_token();
if (!token.is(Token::Type::Ident))
return {};
auto const& ident = token.token().ident();
if (ident.equals_ignoring_ascii_case("dense"sv)) {
transaction.commit();
return GridAutoFlowStyleValue::Dense::Yes;
}
return {};
};
Optional<GridAutoFlowStyleValue::Axis> axis;
Optional<GridAutoFlowStyleValue::Dense> dense;
if (axis = parse_axis(); axis.has_value()) {
dense = parse_dense();
} else if (dense = parse_dense(); dense.has_value()) {
axis = parse_axis();
}
if (tokens.has_next_token())
return nullptr;
return GridAutoFlowStyleValue::create(axis.value_or(GridAutoFlowStyleValue::Axis::Row), dense.value_or(GridAutoFlowStyleValue::Dense::No));
}
RefPtr<StyleValue> Parser::parse_grid_auto_track_sizes(Vector<ComponentValue> const& component_values)
{
// https://www.w3.org/TR/css-grid-2/#auto-tracks
@ -5774,6 +5826,10 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> Parser::parse_css_value(Property
if (auto parsed_value = parse_grid_area_shorthand_value(component_values))
return parsed_value.release_nonnull();
return ParseError::SyntaxError;
case PropertyID::GridAutoFlow:
if (auto parsed_value = parse_grid_auto_flow_value(component_values))
return parsed_value.release_nonnull();
return ParseError::SyntaxError;
case PropertyID::GridTemplateAreas:
if (auto parsed_value = parse_grid_template_areas_value(component_values))
return parsed_value.release_nonnull();

View file

@ -252,6 +252,7 @@ private:
RefPtr<StyleValue> parse_transform_origin_value(Vector<ComponentValue> const&);
RefPtr<StyleValue> parse_grid_track_size_list(Vector<ComponentValue> const&, bool allow_separate_line_name_blocks = false);
RefPtr<StyleValue> parse_grid_auto_track_sizes(Vector<ComponentValue> const&);
[[nodiscard]] RefPtr<GridAutoFlowStyleValue> parse_grid_auto_flow_value(Vector<ComponentValue> const&);
RefPtr<StyleValue> parse_grid_track_size_list_shorthand_value(Vector<ComponentValue> const&);
RefPtr<StyleValue> parse_grid_track_placement(Vector<ComponentValue> const&);
RefPtr<StyleValue> parse_grid_track_placement_shorthand_value(Vector<ComponentValue> const&);

View file

@ -1129,6 +1129,10 @@
],
"percentages-resolve-to": "length"
},
"grid-auto-flow": {
"inherited": false,
"initial": "row"
},
"grid-auto-rows": {
"inherited": false,
"initial": "auto",

View file

@ -12,6 +12,7 @@
#include <LibWeb/CSS/StyleValues/AngleStyleValue.h>
#include <LibWeb/CSS/StyleValues/ContentStyleValue.h>
#include <LibWeb/CSS/StyleValues/DisplayStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
@ -901,6 +902,15 @@ CSS::GridTrackSizeList StyleProperties::grid_template_rows() const
return value->as_grid_track_size_list().grid_track_size_list();
}
CSS::GridAutoFlow StyleProperties::grid_auto_flow() const
{
auto value = property(CSS::PropertyID::GridAutoFlow);
if (!value->is_grid_auto_flow())
return CSS::GridAutoFlow {};
auto& grid_auto_flow_value = value->as_grid_auto_flow();
return CSS::GridAutoFlow { .row = grid_auto_flow_value.is_row(), .dense = grid_auto_flow_value.is_dense() };
}
CSS::GridTrackPlacement StyleProperties::grid_column_end() const
{
auto value = property(CSS::PropertyID::GridColumnEnd);

View file

@ -104,6 +104,7 @@ public:
CSS::GridTrackSizeList grid_auto_rows() const;
CSS::GridTrackSizeList grid_template_columns() const;
CSS::GridTrackSizeList grid_template_rows() const;
[[nodiscard]] CSS::GridAutoFlow grid_auto_flow() const;
CSS::GridTrackPlacement grid_column_end() const;
CSS::GridTrackPlacement grid_column_start() const;
CSS::GridTrackPlacement grid_row_end() const;

View file

@ -33,6 +33,7 @@
#include <LibWeb/CSS/StyleValues/FontStyleValue.h>
#include <LibWeb/CSS/StyleValues/FrequencyStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAreaShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridAutoFlowStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
@ -224,6 +225,12 @@ GridAreaShorthandStyleValue const& StyleValue::as_grid_area_shorthand() const
return static_cast<GridAreaShorthandStyleValue const&>(*this);
}
GridAutoFlowStyleValue const& StyleValue::as_grid_auto_flow() const
{
VERIFY(is_grid_auto_flow());
return static_cast<GridAutoFlowStyleValue const&>(*this);
}
GridTemplateAreaStyleValue const& StyleValue::as_grid_template_area() const
{
VERIFY(is_grid_template_area());

View file

@ -109,6 +109,7 @@ public:
Font,
Frequency,
GridAreaShorthand,
GridAutoFlow,
GridTemplateArea,
GridTrackPlacement,
GridTrackPlacementShorthand,
@ -175,6 +176,7 @@ public:
bool is_grid_track_placement_shorthand() const { return type() == Type::GridTrackPlacementShorthand; }
bool is_grid_track_size_list() const { return type() == Type::GridTrackSizeList; }
bool is_grid_track_size_list_shorthand() const { return type() == Type::GridTrackSizeListShorthand; }
bool is_grid_auto_flow() const { return type() == Type::GridAutoFlow; }
bool is_identifier() const { return type() == Type::Identifier; }
bool is_image() const { return type() == Type::Image; }
bool is_inherit() const { return type() == Type::Inherit; }
@ -235,6 +237,7 @@ public:
GridTrackPlacementStyleValue const& as_grid_track_placement() const;
GridTrackSizeListShorthandStyleValue const& as_grid_track_size_list_shorthand() const;
GridTrackSizeListStyleValue const& as_grid_track_size_list() const;
GridAutoFlowStyleValue const& as_grid_auto_flow() const;
IdentifierStyleValue const& as_identifier() const;
ImageStyleValue const& as_image() const;
InheritStyleValue const& as_inherit() const;
@ -291,6 +294,7 @@ public:
GridTrackPlacementStyleValue& as_grid_track_placement() { return const_cast<GridTrackPlacementStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_placement()); }
GridTrackSizeListShorthandStyleValue& as_grid_track_size_list_shorthand() { return const_cast<GridTrackSizeListShorthandStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_size_list_shorthand()); }
GridTrackSizeListStyleValue& as_grid_track_size_list() { return const_cast<GridTrackSizeListStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_size_list()); }
GridAutoFlowStyleValue& as_grid_auto_flow() { return const_cast<GridAutoFlowStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_auto_flow()); }
IdentifierStyleValue& as_identifier() { return const_cast<IdentifierStyleValue&>(const_cast<StyleValue const&>(*this).as_identifier()); }
ImageStyleValue& as_image() { return const_cast<ImageStyleValue&>(const_cast<StyleValue const&>(*this).as_image()); }
InheritStyleValue& as_inherit() { return const_cast<InheritStyleValue&>(const_cast<StyleValue const&>(*this).as_inherit()); }

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "GridAutoFlowStyleValue.h"
namespace Web::CSS {
ValueComparingNonnullRefPtr<GridAutoFlowStyleValue> GridAutoFlowStyleValue::create(Axis axis, Dense dense)
{
return adopt_ref(*new GridAutoFlowStyleValue(axis, dense));
}
ErrorOr<String> GridAutoFlowStyleValue::to_string() const
{
StringBuilder builder;
if (m_row)
builder.append("row"sv);
else
builder.append("column"sv);
if (m_dense)
builder.append(" dense"sv);
return builder.to_string();
}
}

View file

@ -0,0 +1,45 @@
/*
* Copyright (c) 2023, Andreas Kling <kling@serenityos.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/StyleValue.h>
namespace Web::CSS {
class GridAutoFlowStyleValue final : public StyleValueWithDefaultOperators<GridAutoFlowStyleValue> {
public:
enum Axis {
Row,
Column,
};
enum Dense {
No,
Yes,
};
static ValueComparingNonnullRefPtr<GridAutoFlowStyleValue> create(Axis, Dense);
virtual ~GridAutoFlowStyleValue() override = default;
[[nodiscard]] bool is_row() const { return m_row; }
[[nodiscard]] bool is_column() const { return !m_row; }
[[nodiscard]] bool is_dense() const { return m_dense; }
virtual ErrorOr<String> to_string() const override;
bool properties_equal(GridAutoFlowStyleValue const& other) const { return m_row == other.m_row && m_dense == other.m_dense; }
private:
explicit GridAutoFlowStyleValue(Axis axis, Dense dense)
: StyleValueWithDefaultOperators(Type::GridAutoFlow)
, m_row(axis == Axis::Row)
, m_dense(dense == Dense::Yes)
{
}
bool m_row { false };
bool m_dense { false };
};
}

View file

@ -114,6 +114,7 @@ class FrequencyOrCalculated;
class FrequencyPercentage;
class FrequencyStyleValue;
class GridAreaShorthandStyleValue;
class GridAutoFlowStyleValue;
class GridMinMax;
class GridRepeat;
class GridSize;

View file

@ -724,6 +724,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style)
computed_values.set_grid_row_end(computed_style.grid_row_end());
computed_values.set_grid_row_start(computed_style.grid_row_start());
computed_values.set_grid_template_areas(computed_style.grid_template_areas());
computed_values.set_grid_auto_flow(computed_style.grid_auto_flow());
auto fill = computed_style.property(CSS::PropertyID::Fill);
if (fill->has_color())