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

LibWeb: Fix grid line name placement when repeat() is used

Before this change, parsed grid-template-columns/grid-template-rows
were represented as two lists: line names and track sizes. The problem
with this approach is that it erases the relationship between tracks
and their names, which results in unnecessarily complicated code that
restores this data (incorrectly if repeat() is involved) during layout.
This change solves that by representing line definitions as a list of
sizes and names in the order they were defined.

Visual progression https://genius.com/
This commit is contained in:
Aliaksandr Kalenik 2024-01-05 04:24:36 +01:00 committed by Andreas Kling
parent c4d75ac11a
commit cfcc459140
7 changed files with 168 additions and 104 deletions

View file

@ -188,15 +188,21 @@ String ExplicitGridTrack::to_string() const
}
}
GridTrackSizeList::GridTrackSizeList(Vector<CSS::ExplicitGridTrack> track_list, Vector<Vector<String>> line_names)
: m_track_list(track_list)
, m_line_names(line_names)
String GridLineNames::to_string() const
{
StringBuilder builder;
builder.append("["sv);
builder.join(' ', names);
builder.append("]"sv);
return MUST(builder.to_string());
}
GridTrackSizeList::GridTrackSizeList(Vector<Variant<ExplicitGridTrack, GridLineNames>>&& list)
: m_list(move(list))
{
}
GridTrackSizeList::GridTrackSizeList()
: m_track_list({})
, m_line_names({})
{
}
@ -208,30 +214,38 @@ GridTrackSizeList GridTrackSizeList::make_none()
String GridTrackSizeList::to_string() const
{
StringBuilder builder;
auto print_line_names = [&](size_t index) -> void {
builder.append("["sv);
for (size_t y = 0; y < m_line_names[index].size(); ++y) {
builder.append(m_line_names[index][y]);
if (y != m_line_names[index].size() - 1)
builder.append(" "sv);
}
builder.append("]"sv);
};
for (size_t i = 0; i < m_track_list.size(); ++i) {
if (m_line_names.size() > 0 && m_line_names[i].size() > 0) {
print_line_names(i);
for (auto const& line_definition_or_name : m_list) {
if (!builder.is_empty())
builder.append(" "sv);
if (line_definition_or_name.has<ExplicitGridTrack>()) {
builder.append(line_definition_or_name.get<ExplicitGridTrack>().to_string());
} else if (line_definition_or_name.has<GridLineNames>()) {
auto const& line_names = line_definition_or_name.get<GridLineNames>();
builder.append(line_names.to_string());
}
builder.append(m_track_list[i].to_string());
if (i < m_track_list.size() - 1)
builder.append(" "sv);
}
if (m_line_names.size() > 0 && m_line_names[m_track_list.size()].size() > 0) {
builder.append(" "sv);
print_line_names(m_track_list.size());
}
return MUST(builder.to_string());
}
Vector<ExplicitGridTrack> GridTrackSizeList::track_list() const
{
Vector<ExplicitGridTrack> track_list;
for (auto const& line_definition_or_name : m_list) {
if (line_definition_or_name.has<ExplicitGridTrack>())
track_list.append(line_definition_or_name.get<ExplicitGridTrack>());
}
return track_list;
}
bool GridTrackSizeList::operator==(GridTrackSizeList const& other) const
{
if (m_list.size() != other.m_list.size())
return false;
for (size_t i = 0; i < m_list.size(); ++i) {
if (m_list[i] != other.m_list[i])
return false;
}
return true;
}
}

View file

@ -84,25 +84,28 @@ private:
GridSize m_max_grid_size;
};
struct GridLineNames {
Vector<String> names;
String to_string() const;
bool operator==(GridLineNames const& other) const { return names == other.names; }
};
class GridTrackSizeList {
public:
GridTrackSizeList(Vector<CSS::ExplicitGridTrack> track_list, Vector<Vector<String>> line_names);
GridTrackSizeList(Vector<Variant<ExplicitGridTrack, GridLineNames>>&& list);
GridTrackSizeList();
static GridTrackSizeList make_none();
Vector<CSS::ExplicitGridTrack> track_list() const { return m_track_list; }
Vector<Vector<String>> line_names() const { return m_line_names; }
Vector<CSS::ExplicitGridTrack> track_list() const;
Vector<Variant<ExplicitGridTrack, GridLineNames>> list() const { return m_list; }
String to_string() const;
bool operator==(GridTrackSizeList const& other) const
{
return m_line_names == other.line_names() && m_track_list == other.track_list();
}
bool operator==(GridTrackSizeList const& other) const;
private:
Vector<CSS::ExplicitGridTrack> m_track_list;
Vector<Vector<String>> m_line_names;
Vector<Variant<ExplicitGridTrack, GridLineNames>> m_list;
};
class GridRepeat {

View file

@ -5372,8 +5372,7 @@ Optional<CSS::GridRepeat> Parser::parse_repeat(Vector<ComponentValue> const& com
if (!part_two_tokens.has_next_token())
return {};
Vector<CSS::ExplicitGridTrack> repeat_params;
Vector<Vector<String>> line_names_list;
Vector<Variant<ExplicitGridTrack, GridLineNames>> repeat_params;
auto last_object_was_line_names = false;
while (part_two_tokens.has_next_token()) {
auto token = part_two_tokens.next_token();
@ -5390,7 +5389,7 @@ Optional<CSS::GridRepeat> Parser::parse_repeat(Vector<ComponentValue> const& com
line_names.append(current_block_token.token().ident().to_string());
block_tokens.skip_whitespace();
}
line_names_list.append(line_names);
repeat_params.append(GridLineNames { move(line_names) });
part_two_tokens.skip_whitespace();
} else {
last_object_was_line_names = false;
@ -5408,8 +5407,6 @@ Optional<CSS::GridRepeat> Parser::parse_repeat(Vector<ComponentValue> const& com
part_two_tokens.skip_whitespace();
}
}
while (line_names_list.size() <= repeat_params.size())
line_names_list.append({});
// Thus the precise syntax of the repeat() notation has several forms:
// <track-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <track-size> ]+ <line-names>? )
@ -5431,11 +5428,11 @@ Optional<CSS::GridRepeat> Parser::parse_repeat(Vector<ComponentValue> const& com
// each other, the name lists are merged. For example, repeat(2, [a] 1fr [b]) is equivalent to [a]
// 1fr [b a] 1fr [b].
if (is_auto_fill)
return CSS::GridRepeat(CSS::GridTrackSizeList(repeat_params, line_names_list), CSS::GridRepeat::Type::AutoFill);
return GridRepeat(GridTrackSizeList(move(repeat_params)), GridRepeat::Type::AutoFill);
else if (is_auto_fit)
return CSS::GridRepeat(CSS::GridTrackSizeList(repeat_params, line_names_list), CSS::GridRepeat::Type::AutoFit);
return GridRepeat(GridTrackSizeList(move(repeat_params)), GridRepeat::Type::AutoFit);
else
return CSS::GridRepeat(CSS::GridTrackSizeList(repeat_params, line_names_list), repeat_count);
return GridRepeat(GridTrackSizeList(move(repeat_params)), repeat_count);
}
Optional<CSS::ExplicitGridTrack> Parser::parse_track_sizing_function(ComponentValue const& token)
@ -5480,8 +5477,7 @@ RefPtr<StyleValue> Parser::parse_grid_track_size_list(TokenStream<ComponentValue
return GridTrackSizeListStyleValue::make_none();
}
Vector<CSS::ExplicitGridTrack> track_list;
Vector<Vector<String>> line_names_list;
Vector<Variant<ExplicitGridTrack, GridLineNames>> track_list;
auto last_object_was_line_names = false;
while (tokens.has_next_token()) {
auto token = tokens.next_token();
@ -5503,7 +5499,7 @@ RefPtr<StyleValue> Parser::parse_grid_track_size_list(TokenStream<ComponentValue
line_names.append(current_block_token.token().ident().to_string());
block_tokens.skip_whitespace();
}
line_names_list.append(line_names);
track_list.append(GridLineNames { move(line_names) });
} else {
last_object_was_line_names = false;
auto track_sizing_function = parse_track_sizing_function(token);
@ -5516,11 +5512,9 @@ RefPtr<StyleValue> Parser::parse_grid_track_size_list(TokenStream<ComponentValue
track_list.append(track_sizing_function.value());
}
}
while (line_names_list.size() <= track_list.size())
line_names_list.append({});
transaction.commit();
return GridTrackSizeListStyleValue::create(CSS::GridTrackSizeList(track_list, line_names_list));
return GridTrackSizeListStyleValue::create(GridTrackSizeList(move(track_list)));
}
// https://www.w3.org/TR/css-grid-1/#grid-auto-flow-property
@ -5580,7 +5574,7 @@ RefPtr<StyleValue> Parser::parse_grid_auto_track_sizes(TokenStream<ComponentValu
{
// https://www.w3.org/TR/css-grid-2/#auto-tracks
// <track-size>+
Vector<CSS::ExplicitGridTrack> track_list;
Vector<Variant<ExplicitGridTrack, GridLineNames>> track_list;
auto transaction = tokens.begin_transaction();
while (tokens.has_next_token()) {
auto token = tokens.next_token();
@ -5594,7 +5588,7 @@ RefPtr<StyleValue> Parser::parse_grid_auto_track_sizes(TokenStream<ComponentValu
track_list.append(track_sizing_function.value());
}
transaction.commit();
return GridTrackSizeListStyleValue::create(CSS::GridTrackSizeList(track_list, {}));
return GridTrackSizeListStyleValue::create(GridTrackSizeList(move(track_list)));
}
RefPtr<StyleValue> Parser::parse_grid_track_placement(TokenStream<ComponentValue>& tokens)