mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 22:37:35 +00:00
LibWeb+Base: Add grid repeat() functionality
Add ability to use values passed to grid-template-columns and grid-template-rows for CSS Grid layout within a repeat() function. E.g. grid-template-columns: repeat(2, 50px); means to have two columns of 50px width each.
This commit is contained in:
parent
0b72d237c1
commit
f538dc2fae
3 changed files with 108 additions and 21 deletions
|
@ -49,7 +49,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 0 positioned grid items and similar inputs -->
|
<!-- 0 positioned grid items and similar inputs -->
|
||||||
<div class="grid-container">
|
<div class="grid-container" style="grid-template-rows: repeat(4,[row-start] 1fr [row-end]);">
|
||||||
<div class="grid-item" style="grid-row-end: 0;">2</div>
|
<div class="grid-item" style="grid-row-end: 0;">2</div>
|
||||||
<div class="grid-item" style="grid-row: 0 / 0;">3</div>
|
<div class="grid-item" style="grid-row: 0 / 0;">3</div>
|
||||||
<div class="grid-item" style="grid-column: 0 / 1;">4</div>
|
<div class="grid-item" style="grid-column: 0 / 1;">4</div>
|
||||||
|
@ -104,20 +104,20 @@
|
||||||
|
|
||||||
<!-- Using grid-row and grid-column -->
|
<!-- Using grid-row and grid-column -->
|
||||||
<p>Should render a full-width 4x4 grid with:
|
<p>Should render a full-width 4x4 grid with:
|
||||||
<ul>
|
<ul>
|
||||||
<li>one large column on the left</li>
|
<li>one large column on the left</li>
|
||||||
<li>one large column on the right, being split in half vertically, with the number 2 in the top half, and numbers 3, 4, 5, and 6 in the bottom</li>
|
<li>one large column on the right, being split in half vertically, with the number 2 in the top half, and numbers 3, 4, 5, and 6 in the bottom</li>
|
||||||
</ul>
|
</ul>
|
||||||
<div
|
<div
|
||||||
class="grid-container"
|
class="grid-container"
|
||||||
style="
|
style="
|
||||||
grid-template-columns: 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr;
|
grid-template-columns: repeat(8, 1fr);
|
||||||
grid-template-rows: 25px 25px 25px 25px 25px 25px 25px 25px;
|
grid-template-rows: repeat(2, 25px 25px 25px 25px );
|
||||||
">
|
">
|
||||||
<div class="grid-item" style="grid-row: 1 / -1; grid-column: span 4;">1</div>
|
<div class="grid-item" style="grid-row: 1 / -1; grid-column: span 4;">1</div>
|
||||||
<div class="grid-item" style="grid-row: 1 / 5; grid-column: 5 / -1;">2</div>
|
<div class="grid-item" style="grid-row: 1 / 5; grid-column: 5 / -1;">2</div>
|
||||||
<div class="grid-item" style="grid-column: span 2; grid-row: span 2;">3</div>
|
<div class="grid-item" style="grid-column: span 2; grid-row: span 2;">3</div>
|
||||||
<div class="grid-item" style="grid-column: span 2 / -1; grid-row: span 2;">4</div>
|
<div class="grid-item" style="grid-column: span 2 / -1; grid-row: span 2;">4</div>
|
||||||
<div class="grid-item" style="grid-column: span 2; grid-row: 7 / span 100;">5</div>
|
<div class="grid-item" style="grid-column: span 2; grid-row: 7 / span 100;">5</div>
|
||||||
<div class="grid-item" style="grid-column: 7 / span 2; grid-row: span 2 / -1;">6</div>
|
<div class="grid-item" style="grid-column: 7 / span 2; grid-row: span 2 / -1;">6</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -18,7 +18,6 @@ public:
|
||||||
Percentage,
|
Percentage,
|
||||||
FlexibleLength,
|
FlexibleLength,
|
||||||
// TODO: MinMax
|
// TODO: MinMax
|
||||||
// TODO: Repeat
|
|
||||||
// TODO: Max-Content
|
// TODO: Max-Content
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -5411,9 +5411,97 @@ RefPtr<StyleValue> Parser::parse_grid_track_sizes(Vector<ComponentValue> const&
|
||||||
{
|
{
|
||||||
Vector<CSS::GridTrackSize> params;
|
Vector<CSS::GridTrackSize> params;
|
||||||
for (auto const& component_value : component_values) {
|
for (auto const& component_value : component_values) {
|
||||||
// FIXME: Incomplete as a GridTrackSize can be a function like minmax(min, max), etc.
|
|
||||||
if (component_value.is_function()) {
|
if (component_value.is_function()) {
|
||||||
params.append(Length::make_auto());
|
auto const& function_token = component_value.function();
|
||||||
|
// https://www.w3.org/TR/css-grid-2/#repeat-syntax
|
||||||
|
// 7.2.3.1. Syntax of repeat()
|
||||||
|
// The generic form of the repeat() syntax is, approximately,
|
||||||
|
// repeat( [ <integer [1,∞]> | auto-fill | auto-fit ] , <track-list> )
|
||||||
|
if (function_token.name().equals_ignoring_case("repeat"sv)) {
|
||||||
|
auto function_tokens = TokenStream(function_token.values());
|
||||||
|
auto comma_separated_list = parse_a_comma_separated_list_of_component_values(function_tokens);
|
||||||
|
if (comma_separated_list.size() != 2)
|
||||||
|
continue;
|
||||||
|
// The first argument specifies the number of repetitions.
|
||||||
|
TokenStream part_one_tokens { comma_separated_list[0] };
|
||||||
|
part_one_tokens.skip_whitespace();
|
||||||
|
if (!part_one_tokens.has_next_token())
|
||||||
|
continue;
|
||||||
|
auto current_token = part_one_tokens.next_token().token();
|
||||||
|
|
||||||
|
auto repeat_count = 0;
|
||||||
|
if (current_token.is(Token::Type::Number) && current_token.number().is_integer() && current_token.number_value() > 0)
|
||||||
|
repeat_count = current_token.number_value();
|
||||||
|
|
||||||
|
// The second argument is a track list, which is repeated that number of times.
|
||||||
|
TokenStream part_two_tokens { comma_separated_list[1] };
|
||||||
|
part_two_tokens.skip_whitespace();
|
||||||
|
if (!part_two_tokens.has_next_token())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Vector<CSS::GridTrackSize> repeat_params;
|
||||||
|
while (true) {
|
||||||
|
part_two_tokens.skip_whitespace();
|
||||||
|
auto current_component_value = part_two_tokens.next_token();
|
||||||
|
if (current_component_value.is_function()) {
|
||||||
|
// However, there are some restrictions:
|
||||||
|
// The repeat() notation can’t be nested.
|
||||||
|
if (current_component_value.function().name().equals_ignoring_case("repeat"sv))
|
||||||
|
return GridTrackSizeStyleValue::create({});
|
||||||
|
|
||||||
|
// FIXME: Implement MinMax, etc.
|
||||||
|
} else if (current_component_value.is_block()) {
|
||||||
|
// FIXME: Implement things like grid-template-columns: repeat(1, [col-start] 8);
|
||||||
|
} else {
|
||||||
|
current_token = current_component_value.token();
|
||||||
|
if (current_token.type() == Token::Type::Dimension && current_token.dimension_unit().equals_ignoring_case("fr"sv)) {
|
||||||
|
float numeric_value = current_token.dimension_value();
|
||||||
|
if (numeric_value)
|
||||||
|
repeat_params.append(GridTrackSize(numeric_value));
|
||||||
|
} else {
|
||||||
|
auto dimension = parse_dimension(current_token);
|
||||||
|
if (!dimension.has_value())
|
||||||
|
return GridTrackSizeStyleValue::create({});
|
||||||
|
if (dimension->is_length())
|
||||||
|
repeat_params.append(GridTrackSize(dimension->length()));
|
||||||
|
else if (dimension->is_percentage())
|
||||||
|
repeat_params.append(GridTrackSize(dimension->percentage()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
part_two_tokens.skip_whitespace();
|
||||||
|
if (!part_two_tokens.has_next_token()) {
|
||||||
|
for (int i = 0; i < repeat_count; ++i) {
|
||||||
|
for (auto const& repeat_param : repeat_params)
|
||||||
|
params.append(repeat_param);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Automatic repetitions (auto-fill or auto-fit) cannot be combined with intrinsic or flexible sizes.
|
||||||
|
|
||||||
|
// Thus the precise syntax of the repeat() notation has several forms:
|
||||||
|
// <track-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <track-size> ]+ <line-names>? )
|
||||||
|
// <auto-repeat> = repeat( [ auto-fill | auto-fit ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
|
||||||
|
// <fixed-repeat> = repeat( [ <integer [1,∞]> ] , [ <line-names>? <fixed-size> ]+ <line-names>? )
|
||||||
|
// <name-repeat> = repeat( [ <integer [1,∞]> | auto-fill ], <line-names>+)
|
||||||
|
|
||||||
|
// The <track-repeat> variant can represent the repetition of any <track-size>, but is limited to a
|
||||||
|
// fixed number of repetitions.
|
||||||
|
|
||||||
|
// The <auto-repeat> variant can repeat automatically to fill a space, but requires definite track
|
||||||
|
// sizes so that the number of repetitions can be calculated. It can only appear once in the track
|
||||||
|
// list, but the same track list can also contain <fixed-repeat>s.
|
||||||
|
|
||||||
|
// The <name-repeat> variant is for adding line names to subgrids. It can only be used with the
|
||||||
|
// subgrid keyword and cannot specify track sizes, only line names.
|
||||||
|
|
||||||
|
// If a repeat() function that is not a <name-repeat> ends up placing two <line-names> adjacent to
|
||||||
|
// each other, the name lists are merged. For example, repeat(2, [a] 1fr [b]) is equivalent to [a]
|
||||||
|
// 1fr [b a] 1fr [b].
|
||||||
|
} else {
|
||||||
|
// FIXME: Implement MinMax, etc.
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (component_value.is_block()) {
|
if (component_value.is_block()) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue