1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-27 16:47:44 +00:00

LibWeb: Parse grid-template property

This commit is contained in:
martinfalisse 2023-04-29 19:32:56 +02:00 committed by Andreas Kling
parent bebf4363db
commit 22202715fc
13 changed files with 351 additions and 3 deletions

View file

@ -87,6 +87,7 @@ set(SOURCES
CSS/StyleValues/GridTemplateAreaStyleValue.cpp
CSS/StyleValues/GridTrackPlacementStyleValue.cpp
CSS/StyleValues/GridTrackPlacementShorthandStyleValue.cpp
CSS/StyleValues/GridTrackSizeListShorthandStyleValue.cpp
CSS/StyleValues/GridTrackSizeListStyleValue.cpp
CSS/StyleValues/IdentifierStyleValue.cpp
CSS/StyleValues/ImageStyleValue.cpp

View file

@ -51,6 +51,7 @@
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
#include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
#include <LibWeb/CSS/StyleValues/ImageStyleValue.h>
@ -6269,7 +6270,7 @@ Optional<CSS::ExplicitGridTrack> Parser::parse_track_sizing_function(ComponentVa
}
}
RefPtr<StyleValue> Parser::parse_grid_track_size_list(Vector<ComponentValue> const& component_values)
RefPtr<StyleValue> Parser::parse_grid_track_size_list(Vector<ComponentValue> const& component_values, bool allow_separate_line_name_blocks)
{
Vector<CSS::ExplicitGridTrack> track_list;
Vector<Vector<String>> line_names_list;
@ -6278,7 +6279,7 @@ RefPtr<StyleValue> Parser::parse_grid_track_size_list(Vector<ComponentValue> con
while (tokens.has_next_token()) {
auto token = tokens.next_token();
if (token.is_block()) {
if (last_object_was_line_names)
if (last_object_was_line_names && !allow_separate_line_name_blocks)
return GridTrackSizeListStyleValue::make_auto();
last_object_was_line_names = true;
Vector<String> line_names;
@ -6445,6 +6446,53 @@ RefPtr<StyleValue> Parser::parse_grid_track_placement_shorthand_value(Vector<Com
return {};
}
// https://www.w3.org/TR/css-grid-2/#explicit-grid-shorthand
// 7.4. Explicit Grid Shorthand: the grid-template property
RefPtr<StyleValue> Parser::parse_grid_track_size_list_shorthand_value(Vector<ComponentValue> const& component_values)
{
// The grid-template property is a shorthand for setting grid-template-columns, grid-template-rows,
// and grid-template-areas in a single declaration. It has several distinct syntax forms:
// none
// - Sets all three properties to their initial values (none).
// <'grid-template-rows'> / <'grid-template-columns'>
// - Sets grid-template-rows and grid-template-columns to the specified values, respectively, and sets grid-template-areas to none.
// [ <line-names>? <string> <track-size>? <line-names>? ]+ [ / <explicit-track-list> ]?
// - Sets grid-template-areas to the strings listed.
// - Sets grid-template-rows to the <track-size>s following each string (filling in auto for any missing sizes),
// and splicing in the named lines defined before/after each size.
// - Sets grid-template-columns to the track listing specified after the slash (or none, if not specified).
Vector<ComponentValue> template_rows_tokens;
Vector<ComponentValue> template_columns_tokens;
Vector<ComponentValue> template_area_tokens;
int forward_slash_index = -1;
for (size_t x = 0; x < component_values.size(); x++) {
if (component_values[x].is_token() && component_values[x].token().is(Token::Type::Delim) && component_values[x].token().delim() == "/"sv) {
forward_slash_index = x;
break;
}
}
for (size_t x = 0; x < (forward_slash_index > -1 ? forward_slash_index : component_values.size()); x++) {
if (component_values[x].is_token() && component_values[x].token().is(Token::Type::String))
template_area_tokens.append(component_values[x]);
else
template_rows_tokens.append(component_values[x]);
}
if (forward_slash_index > -1) {
for (size_t x = forward_slash_index + 1; x < component_values.size(); x++)
template_columns_tokens.append(component_values[x]);
}
auto parsed_template_areas_values = parse_grid_template_areas_value(template_area_tokens);
auto parsed_template_rows_values = parse_grid_track_size_list(template_rows_tokens, true);
auto parsed_template_columns_values = parse_grid_track_size_list(template_columns_tokens);
return GridTrackSizeListShorthandStyleValue::create(
parsed_template_areas_values.release_nonnull()->as_grid_template_area(),
parsed_template_rows_values.release_nonnull()->as_grid_track_size_list(),
parsed_template_columns_values.release_nonnull()->as_grid_track_size_list());
}
RefPtr<StyleValue> Parser::parse_grid_area_shorthand_value(Vector<ComponentValue> const& component_values)
{
auto tokens = TokenStream { component_values };
@ -6708,6 +6756,10 @@ Parser::ParseErrorOr<NonnullRefPtr<StyleValue>> Parser::parse_css_value(Property
if (auto parsed_value = parse_grid_track_placement(component_values))
return parsed_value.release_nonnull();
return ParseError::SyntaxError;
case PropertyID::GridTemplate:
if (auto parsed_value = parse_grid_track_size_list_shorthand_value(component_values))
return parsed_value.release_nonnull();
return ParseError::SyntaxError;
case PropertyID::GridTemplateColumns:
if (auto parsed_value = parse_grid_track_size_list(component_values))
return parsed_value.release_nonnull();

View file

@ -318,7 +318,8 @@ private:
RefPtr<StyleValue> parse_text_decoration_line_value(TokenStream<ComponentValue>&);
RefPtr<StyleValue> parse_transform_value(Vector<ComponentValue> const&);
RefPtr<StyleValue> parse_transform_origin_value(Vector<ComponentValue> const&);
RefPtr<StyleValue> parse_grid_track_size_list(Vector<ComponentValue> const&);
RefPtr<StyleValue> parse_grid_track_size_list(Vector<ComponentValue> const&, bool allow_separate_line_name_blocks = false);
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&);
RefPtr<StyleValue> parse_grid_template_areas_value(Vector<ComponentValue> const&);

View file

@ -941,6 +941,23 @@
"string"
]
},
"grid-template": {
"inherited": false,
"initial": "auto",
"valid-identifiers": [
"auto"
],
"valid-types": [
"length",
"percentage",
"string"
],
"longhands": [
"grid-template-areas",
"grid-template-rows",
"grid-template-columns"
]
},
"grid-template-areas": {
"inherited": false,
"initial": "auto",

View file

@ -23,6 +23,7 @@
#include <LibWeb/CSS/StyleValues/GridAreaShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
#include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
#include <LibWeb/CSS/StyleValues/InitialStyleValue.h>
@ -484,6 +485,26 @@ RefPtr<StyleValue const> ResolvedCSSStyleDeclaration::style_value_for_property(L
return GridTrackPlacementStyleValue::create(layout_node.computed_values().grid_row_end());
case CSS::PropertyID::GridRowStart:
return GridTrackPlacementStyleValue::create(layout_node.computed_values().grid_row_start());
case CSS::PropertyID::GridTemplate: {
auto maybe_grid_template_areas = property(CSS::PropertyID::GridTemplateAreas);
auto maybe_grid_template_rows = property(CSS::PropertyID::GridTemplateRows);
auto maybe_grid_template_columns = property(CSS::PropertyID::GridTemplateColumns);
RefPtr<GridTemplateAreaStyleValue const> grid_template_areas;
RefPtr<GridTrackSizeListStyleValue const> grid_template_rows, grid_template_columns;
if (maybe_grid_template_areas.has_value()) {
VERIFY(maybe_grid_template_areas.value().value->is_grid_template_area());
grid_template_areas = maybe_grid_template_areas.value().value->as_grid_template_area();
}
if (maybe_grid_template_rows.has_value()) {
VERIFY(maybe_grid_template_rows.value().value->is_grid_track_size_list());
grid_template_rows = maybe_grid_template_rows.value().value->as_grid_track_size_list();
}
if (maybe_grid_template_columns.has_value()) {
VERIFY(maybe_grid_template_columns.value().value->is_grid_track_size_list());
grid_template_columns = maybe_grid_template_columns.value().value->as_grid_track_size_list();
}
return GridTrackSizeListShorthandStyleValue::create(grid_template_areas.release_nonnull(), grid_template_rows.release_nonnull(), grid_template_columns.release_nonnull());
}
case CSS::PropertyID::GridTemplateColumns:
return GridTrackSizeListStyleValue::create(layout_node.computed_values().grid_template_columns());
case CSS::PropertyID::GridTemplateRows:

View file

@ -37,6 +37,8 @@
#include <LibWeb/CSS/StyleValues/GridAreaShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
#include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
#include <LibWeb/CSS/StyleValues/LengthStyleValue.h>
#include <LibWeb/CSS/StyleValues/ListStyleStyleValue.h>
@ -623,6 +625,20 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope
return;
}
if (property_id == CSS::PropertyID::GridTemplate) {
if (value.is_grid_track_size_list_shorthand()) {
auto const& shorthand = value.as_grid_track_size_list_shorthand();
style.set_property(CSS::PropertyID::GridTemplateAreas, shorthand.areas());
style.set_property(CSS::PropertyID::GridTemplateRows, shorthand.rows());
style.set_property(CSS::PropertyID::GridTemplateColumns, shorthand.columns());
return;
}
style.set_property(CSS::PropertyID::GridTemplateAreas, value);
style.set_property(CSS::PropertyID::GridTemplateRows, value);
style.set_property(CSS::PropertyID::GridTemplateColumns, value);
return;
}
if (property_id == CSS::PropertyID::Gap || property_id == CSS::PropertyID::GridGap) {
if (value.is_value_list()) {
auto const& values_list = value.as_value_list();

View file

@ -30,6 +30,7 @@
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListShorthandStyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
#include <LibWeb/CSS/StyleValues/IdentifierStyleValue.h>
#include <LibWeb/CSS/StyleValues/ImageStyleValue.h>
@ -236,6 +237,12 @@ GridTrackSizeListStyleValue const& StyleValue::as_grid_track_size_list() const
return static_cast<GridTrackSizeListStyleValue const&>(*this);
}
GridTrackSizeListShorthandStyleValue const& StyleValue::as_grid_track_size_list_shorthand() const
{
VERIFY(is_grid_track_size_list_shorthand());
return static_cast<GridTrackSizeListShorthandStyleValue const&>(*this);
}
LinearGradientStyleValue const& StyleValue::as_linear_gradient() const
{
VERIFY(is_linear_gradient());

View file

@ -109,6 +109,7 @@ public:
GridTrackPlacement,
GridTrackPlacementShorthand,
GridTrackSizeList,
GridTrackSizeListShorthand,
Identifier,
Image,
Inherit,
@ -160,6 +161,7 @@ public:
bool is_grid_track_placement() const { return type() == Type::GridTrackPlacement; }
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_identifier() const { return type() == Type::Identifier; }
bool is_image() const { return type() == Type::Image; }
bool is_inherit() const { return type() == Type::Inherit; }
@ -208,6 +210,7 @@ public:
GridTemplateAreaStyleValue const& as_grid_template_area() const;
GridTrackPlacementShorthandStyleValue const& as_grid_track_placement_shorthand() const;
GridTrackPlacementStyleValue const& as_grid_track_placement() const;
GridTrackSizeListShorthandStyleValue const& as_grid_track_size_list_shorthand() const;
GridTrackSizeListStyleValue const& as_grid_track_size_list() const;
IdentifierStyleValue const& as_identifier() const;
ImageStyleValue const& as_image() const;
@ -255,6 +258,7 @@ public:
GridTemplateAreaStyleValue& as_grid_template_area() { return const_cast<GridTemplateAreaStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_template_area()); }
GridTrackPlacementShorthandStyleValue& as_grid_track_placement_shorthand() { return const_cast<GridTrackPlacementShorthandStyleValue&>(const_cast<StyleValue const&>(*this).as_grid_track_placement_shorthand()); }
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()); }
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()); }

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2023, Martin Falisse <mfalisse@outlook.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include "GridTrackSizeListShorthandStyleValue.h"
#include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h>
namespace Web::CSS {
ValueComparingNonnullRefPtr<GridTrackSizeListShorthandStyleValue> GridTrackSizeListShorthandStyleValue::create(
ValueComparingNonnullRefPtr<GridTemplateAreaStyleValue const> areas,
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> rows,
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> columns)
{
return adopt_ref(*new GridTrackSizeListShorthandStyleValue(move(areas), move(rows), move(columns)));
}
ErrorOr<String> GridTrackSizeListShorthandStyleValue::to_string() const
{
auto construct_rows_string = [&]() -> ErrorOr<String> {
StringBuilder builder;
size_t idx = 0;
for (auto const& row : m_properties.rows->grid_track_size_list().track_list()) {
if (m_properties.areas->grid_template_area().size() > idx) {
TRY(builder.try_append("\""sv));
for (size_t y = 0; y < m_properties.areas->grid_template_area()[idx].size(); ++y) {
TRY(builder.try_append(m_properties.areas->grid_template_area()[idx][y]));
if (y != m_properties.areas->grid_template_area()[idx].size() - 1)
TRY(builder.try_append(" "sv));
}
TRY(builder.try_append("\" "sv));
}
TRY(builder.try_append(TRY(row.to_string())));
if (idx < m_properties.rows->grid_track_size_list().track_list().size() - 1)
TRY(builder.try_append(' '));
idx++;
}
return TRY(builder.to_string());
};
if (m_properties.columns->grid_track_size_list().track_list().size() == 0)
return String::formatted("{}", TRY(construct_rows_string()));
return String::formatted("{} / {}", TRY(construct_rows_string()), TRY(m_properties.columns->grid_track_size_list().to_string()));
}
}

View file

@ -0,0 +1,48 @@
/*
* Copyright (c) 2023, Martin Falisse <mfalisse@outlook.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <LibWeb/CSS/StyleValue.h>
#include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h>
namespace Web::CSS {
class GridTrackSizeListShorthandStyleValue final : public StyleValueWithDefaultOperators<GridTrackSizeListShorthandStyleValue> {
public:
static ValueComparingNonnullRefPtr<GridTrackSizeListShorthandStyleValue> create(
ValueComparingNonnullRefPtr<GridTemplateAreaStyleValue const> areas,
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> rows,
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> columns);
virtual ~GridTrackSizeListShorthandStyleValue() override = default;
auto rows() const { return m_properties.rows; }
auto columns() const { return m_properties.columns; }
auto areas() const { return m_properties.areas; }
virtual ErrorOr<String> to_string() const override;
bool properties_equal(GridTrackSizeListShorthandStyleValue const& other) const { return m_properties == other.m_properties; };
private:
GridTrackSizeListShorthandStyleValue(
ValueComparingNonnullRefPtr<GridTemplateAreaStyleValue const> areas,
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> rows,
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> columns)
: StyleValueWithDefaultOperators(Type::GridTrackSizeListShorthand)
, m_properties { .areas = move(areas), .rows = move(rows), .columns = move(columns) }
{
}
struct Properties {
ValueComparingNonnullRefPtr<GridTemplateAreaStyleValue const> areas;
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> rows;
ValueComparingNonnullRefPtr<GridTrackSizeListStyleValue const> columns;
bool operator==(Properties const&) const = default;
} m_properties;
};
}

View file

@ -105,6 +105,7 @@ class GridTrackPlacement;
class GridTrackPlacementShorthandStyleValue;
class GridTrackPlacementStyleValue;
class GridTrackSizeList;
class GridTrackSizeListShorthandStyleValue;
class GridTrackSizeListStyleValue;
class IdentifierStyleValue;
class ImageStyleValue;