mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-16 05:51:55 +00:00
LibWeb: Parse grid track placements closer to spec
This brings parsing of grid-row-* and grid-column-* properties (and their associated shorthands) more inline with spec. Changes: - Only set omitted properties for combined-value shorthands (e.g. `grid-row: a` rather than `grid-row: a / b`) if the single value is `<custom-ident>`. - `[ [ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>? ]`: - Properly resolve `calc`s for `<integer>` that rely on compute-time information. - `[ span && [ <integer [1,∞]> || <custom-ident> ] ]` - Allow `calc`s for `<integer>` - Allow `<custom-ident>` There is still work to be done to properly use these parsed values. Gains us 46 WPT tests.
This commit is contained in:
parent
a424a06d45
commit
36e2d25efa
Notes:
github-actions[bot]
2025-07-08 16:27:31 +00:00
Author: https://github.com/Calme1709
Commit: 36e2d25efa
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/5346
Reviewed-by: https://github.com/tcl3 ✅
12 changed files with 153 additions and 171 deletions
|
@ -19,15 +19,21 @@ String GridTrackPlacement::to_string() const
|
|||
},
|
||||
[&](AreaOrLine const& area_or_line) {
|
||||
if (area_or_line.line_number.has_value() && area_or_line.name.has_value()) {
|
||||
builder.appendff("{} {}", *area_or_line.line_number, *area_or_line.name);
|
||||
builder.appendff("{} {}", area_or_line.line_number->to_string(), *area_or_line.name);
|
||||
} else if (area_or_line.line_number.has_value()) {
|
||||
builder.appendff("{}", *area_or_line.line_number);
|
||||
builder.appendff("{}", area_or_line.line_number->to_string());
|
||||
} else if (area_or_line.name.has_value()) {
|
||||
builder.appendff("{}", *area_or_line.name);
|
||||
}
|
||||
},
|
||||
[&](Span const& span) {
|
||||
builder.appendff("span {}", span.value);
|
||||
builder.append("span"sv);
|
||||
|
||||
if (!span.name.has_value() || span.value.is_calculated() || span.value.value() != 1)
|
||||
builder.appendff(" {}", span.value.to_string());
|
||||
|
||||
if (span.name.has_value())
|
||||
builder.appendff(" {}", span.name.value());
|
||||
});
|
||||
return MUST(builder.to_string());
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <AK/String.h>
|
||||
#include <LibWeb/CSS/CalculatedOr.h>
|
||||
|
||||
namespace Web::CSS {
|
||||
|
||||
|
@ -18,14 +19,14 @@ public:
|
|||
return GridTrackPlacement();
|
||||
}
|
||||
|
||||
static GridTrackPlacement make_line(Optional<int> line_number, Optional<String> name)
|
||||
static GridTrackPlacement make_line(Optional<IntegerOrCalculated> line_number, Optional<String> name)
|
||||
{
|
||||
return GridTrackPlacement(AreaOrLine { .line_number = line_number, .name = name });
|
||||
}
|
||||
|
||||
static GridTrackPlacement make_span(int value)
|
||||
static GridTrackPlacement make_span(IntegerOrCalculated value, Optional<String> name)
|
||||
{
|
||||
return GridTrackPlacement(Span { .value = value });
|
||||
return GridTrackPlacement(Span { .value = value, .name = name });
|
||||
}
|
||||
|
||||
bool is_auto() const { return m_value.has<Auto>(); }
|
||||
|
@ -35,6 +36,8 @@ public:
|
|||
bool is_auto_positioned() const { return is_auto() || is_span(); }
|
||||
bool is_positioned() const { return !is_auto_positioned(); }
|
||||
|
||||
bool is_custom_ident() const { return is_area_or_line() && !m_value.get<AreaOrLine>().line_number.has_value(); }
|
||||
|
||||
bool has_identifier() const
|
||||
{
|
||||
return is_area_or_line() && m_value.get<AreaOrLine>().name.has_value();
|
||||
|
@ -47,8 +50,8 @@ public:
|
|||
|
||||
String identifier() const { return *m_value.get<AreaOrLine>().name; }
|
||||
|
||||
int line_number() const { return *m_value.get<AreaOrLine>().line_number; }
|
||||
int span() const { return m_value.get<Span>().value; }
|
||||
IntegerOrCalculated line_number() const { return *m_value.get<AreaOrLine>().line_number; }
|
||||
IntegerOrCalculated span() const { return m_value.get<Span>().value; }
|
||||
|
||||
String to_string() const;
|
||||
|
||||
|
@ -60,13 +63,14 @@ private:
|
|||
};
|
||||
|
||||
struct AreaOrLine {
|
||||
Optional<int> line_number;
|
||||
Optional<IntegerOrCalculated> line_number;
|
||||
Optional<String> name;
|
||||
bool operator==(AreaOrLine const& other) const = default;
|
||||
};
|
||||
|
||||
struct Span {
|
||||
int value;
|
||||
IntegerOrCalculated value;
|
||||
Optional<String> name;
|
||||
bool operator==(Span const& other) const = default;
|
||||
};
|
||||
|
||||
|
|
|
@ -4528,7 +4528,7 @@ RefPtr<CSSStyleValue const> Parser::parse_grid_track_placement_shorthand_value(P
|
|||
auto parsed_start_value = parse_grid_track_placement(track_start_placement_token_stream);
|
||||
if (parsed_start_value && track_end_placement_tokens.is_empty()) {
|
||||
transaction.commit();
|
||||
if (parsed_start_value->grid_track_placement().has_identifier()) {
|
||||
if (parsed_start_value->grid_track_placement().is_custom_ident()) {
|
||||
auto custom_ident = parsed_start_value.release_nonnull();
|
||||
return ShorthandStyleValue::create(property_id, { start_property, end_property }, { custom_ident, custom_ident });
|
||||
}
|
||||
|
@ -4721,21 +4721,21 @@ RefPtr<CSSStyleValue const> Parser::parse_grid_area_shorthand_value(TokenStream<
|
|||
// that value. Otherwise, it is set to auto.
|
||||
if (column_start_style_value)
|
||||
column_start = column_start_style_value.release_nonnull()->as_grid_track_placement().grid_track_placement();
|
||||
else
|
||||
else if (row_start.is_custom_ident())
|
||||
column_start = row_start;
|
||||
|
||||
// When grid-row-end is omitted, if grid-row-start is a <custom-ident>, grid-row-end is set to that
|
||||
// <custom-ident>; otherwise, it is set to auto.
|
||||
if (row_end_style_value)
|
||||
row_end = row_end_style_value.release_nonnull()->as_grid_track_placement().grid_track_placement();
|
||||
else
|
||||
else if (row_start.is_custom_ident())
|
||||
row_end = row_start;
|
||||
|
||||
// When grid-column-end is omitted, if grid-column-start is a <custom-ident>, grid-column-end is set to
|
||||
// that <custom-ident>; otherwise, it is set to auto.
|
||||
if (column_end_style_value)
|
||||
column_end = column_end_style_value.release_nonnull()->as_grid_track_placement().grid_track_placement();
|
||||
else
|
||||
else if (column_start.is_custom_ident())
|
||||
column_end = column_start;
|
||||
|
||||
transaction.commit();
|
||||
|
|
|
@ -3647,108 +3647,72 @@ GridTrackSizeList Parser::parse_explicit_track_list(TokenStream<ComponentValue>&
|
|||
|
||||
RefPtr<GridTrackPlacementStyleValue const> Parser::parse_grid_track_placement(TokenStream<ComponentValue>& tokens)
|
||||
{
|
||||
// FIXME: This shouldn't be needed. Right now, the below code returns a CSSStyleValue even if no tokens are consumed!
|
||||
if (!tokens.has_next_token())
|
||||
return nullptr;
|
||||
|
||||
if (tokens.remaining_token_count() > 3)
|
||||
return nullptr;
|
||||
|
||||
// https://www.w3.org/TR/css-grid-2/#line-placement
|
||||
// Line-based Placement: the grid-row-start, grid-column-start, grid-row-end, and grid-column-end properties
|
||||
// <grid-line> =
|
||||
// auto |
|
||||
// <custom-ident> |
|
||||
// [ <integer> && <custom-ident>? ] |
|
||||
// [ span && [ <integer> || <custom-ident> ] ]
|
||||
auto is_valid_integer = [](auto& token) -> bool {
|
||||
// An <integer> value of zero makes the declaration invalid.
|
||||
if (token.is(Token::Type::Number) && token.token().number().is_integer() && token.token().number_value() != 0)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
auto parse_custom_ident = [this](auto& tokens) {
|
||||
// The <custom-ident> additionally excludes the keywords span and auto.
|
||||
return parse_custom_ident_value(tokens, { { "span"sv, "auto"sv } });
|
||||
};
|
||||
// [ [ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>? ] |
|
||||
// [ span && [ <integer [1,∞]> || <custom-ident> ] ]
|
||||
bool is_span = false;
|
||||
Optional<String> parsed_custom_ident;
|
||||
Optional<IntegerOrCalculated> parsed_integer;
|
||||
|
||||
auto transaction = tokens.begin_transaction();
|
||||
|
||||
// FIXME: Handle the single-token case inside the loop instead, so that we can more easily call this from
|
||||
// `parse_grid_area_shorthand_value()` using a single TokenStream.
|
||||
if (tokens.remaining_token_count() == 1) {
|
||||
if (auto custom_ident = parse_custom_ident(tokens)) {
|
||||
transaction.commit();
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line({}, custom_ident->custom_ident().to_string()));
|
||||
}
|
||||
auto const& token = tokens.consume_a_token();
|
||||
if (auto maybe_calculated = parse_calculated_value(token)) {
|
||||
if (maybe_calculated->is_number()) {
|
||||
transaction.commit();
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(maybe_calculated->as_number().number()), {}));
|
||||
}
|
||||
if (maybe_calculated->is_calculated() && maybe_calculated->as_calculated().resolves_to_number()) {
|
||||
transaction.commit();
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(maybe_calculated->as_calculated().resolve_integer({}).value()), {}));
|
||||
}
|
||||
}
|
||||
if (token.is_ident("auto"sv)) {
|
||||
if (tokens.remaining_token_count() == 1 && tokens.next_token().is_ident("auto"sv)) {
|
||||
tokens.discard_a_token();
|
||||
transaction.commit();
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_auto());
|
||||
}
|
||||
if (is_valid_integer(token)) {
|
||||
transaction.commit();
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(token.token().number_value()), {}));
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto span_value = false;
|
||||
auto span_or_position_value = 0;
|
||||
String identifier_value;
|
||||
while (tokens.has_next_token()) {
|
||||
auto const& token = tokens.next_token();
|
||||
if (token.is_ident("auto"sv))
|
||||
return nullptr;
|
||||
if (token.is_ident("span"sv)) {
|
||||
if (span_value)
|
||||
return nullptr;
|
||||
tokens.discard_a_token(); // span
|
||||
if (tokens.has_next_token() && ((span_or_position_value != 0 && identifier_value.is_empty()) || (span_or_position_value == 0 && !identifier_value.is_empty())))
|
||||
return nullptr;
|
||||
span_value = true;
|
||||
continue;
|
||||
}
|
||||
if (is_valid_integer(token)) {
|
||||
if (span_or_position_value != 0)
|
||||
return nullptr;
|
||||
span_or_position_value = static_cast<int>(tokens.consume_a_token().token().to_integer());
|
||||
continue;
|
||||
}
|
||||
if (auto custom_ident = parse_custom_ident(tokens)) {
|
||||
if (!identifier_value.is_empty())
|
||||
return nullptr;
|
||||
identifier_value = custom_ident->custom_ident().to_string();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (tokens.has_next_token())
|
||||
if (tokens.next_token().is_ident("span"sv)) {
|
||||
if (is_span)
|
||||
return nullptr;
|
||||
|
||||
// Negative integers or zero are invalid.
|
||||
if (span_value && span_or_position_value < 1)
|
||||
tokens.discard_a_token();
|
||||
|
||||
// NOTE: "span" must not appear in between <custom-ident> and <integer>
|
||||
if (tokens.has_next_token() && (parsed_custom_ident.has_value() || parsed_integer.has_value()))
|
||||
return nullptr;
|
||||
|
||||
// If the <integer> is omitted, it defaults to 1.
|
||||
if (span_or_position_value == 0)
|
||||
span_or_position_value = 1;
|
||||
is_span = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto maybe_parsed_custom_ident = parse_custom_ident(tokens, { { "auto"sv } }); maybe_parsed_custom_ident.has_value()) {
|
||||
if (parsed_custom_ident.has_value())
|
||||
return nullptr;
|
||||
|
||||
parsed_custom_ident = maybe_parsed_custom_ident->to_string();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (auto maybe_parsed_integer = parse_integer(tokens); maybe_parsed_integer.has_value()) {
|
||||
if (parsed_integer.has_value())
|
||||
return nullptr;
|
||||
|
||||
parsed_integer = maybe_parsed_integer;
|
||||
continue;
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
transaction.commit();
|
||||
if (!identifier_value.is_empty())
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(span_or_position_value, identifier_value));
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_span(span_or_position_value));
|
||||
|
||||
// <custom-ident>
|
||||
// [ [ <integer [-∞,-1]> | <integer [1,∞]> ] && <custom-ident>? ]
|
||||
if (!is_span && (parsed_integer.has_value() || parsed_custom_ident.has_value()) && (!parsed_integer.has_value() || parsed_integer.value().is_calculated() || parsed_integer.value().value() != 0))
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(parsed_integer, parsed_custom_ident));
|
||||
|
||||
// [ span && [ <integer [1,∞]> || <custom-ident> ] ]
|
||||
if (is_span && (parsed_integer.has_value() || parsed_custom_ident.has_value()) && (!parsed_integer.has_value() || parsed_integer.value().is_calculated() || parsed_integer.value().value() > 0))
|
||||
// If the <integer> is omitted, it defaults to 1.
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_span(parsed_integer.value_or(1), parsed_custom_ident));
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CSSStyleValue const> Parser::parse_calculated_value(ComponentValue const& component_value)
|
||||
|
|
|
@ -282,16 +282,21 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
|||
auto const& placement_start = dimension == GridDimension::Row ? computed_values.grid_row_start() : computed_values.grid_column_start();
|
||||
auto const& placement_end = dimension == GridDimension::Row ? computed_values.grid_row_end() : computed_values.grid_column_end();
|
||||
|
||||
CSS::CalculationResolutionContext resolution_context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(child_box) };
|
||||
|
||||
Optional<i64> placement_start_line_number = placement_start.has_line_number() ? placement_start.line_number().resolved(resolution_context) : Optional<i64> {};
|
||||
Optional<i64> placement_end_line_number = placement_end.has_line_number() ? placement_end.line_number().resolved(resolution_context) : Optional<i64> {};
|
||||
|
||||
PlacementPosition result;
|
||||
|
||||
if (placement_start.has_line_number() && placement_start.line_number() > 0)
|
||||
result.start = placement_start.line_number() - 1;
|
||||
else if (placement_start.has_line_number()) {
|
||||
if (placement_start_line_number.has_value() && placement_start_line_number.value() > 0)
|
||||
result.start = placement_start_line_number.value() - 1;
|
||||
else if (placement_start_line_number.has_value()) {
|
||||
auto explicit_line_count = dimension == GridDimension::Row ? m_explicit_rows_line_count : m_explicit_columns_line_count;
|
||||
result.start = explicit_line_count + placement_start.line_number();
|
||||
result.start = explicit_line_count + placement_start_line_number.value();
|
||||
}
|
||||
if (placement_end.has_line_number())
|
||||
result.end = placement_end.line_number() - 1;
|
||||
if (placement_end_line_number.has_value())
|
||||
result.end = *placement_end_line_number - 1;
|
||||
|
||||
if (result.end < 0) {
|
||||
if (dimension == GridDimension::Row)
|
||||
|
@ -300,10 +305,13 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
|||
result.end = m_occupation_grid.column_count() + result.end + 2;
|
||||
}
|
||||
|
||||
// FIXME: If a name is given as a <custom-ident>, only lines with that name are counted. If not enough lines with
|
||||
// that name exist, all implicit grid lines on the side of the explicit grid corresponding to the search
|
||||
// direction are assumed to have that name for the purpose of counting this span.
|
||||
if (placement_end.is_span())
|
||||
result.span = placement_end.span();
|
||||
result.span = placement_end.span().resolved(resolution_context).value();
|
||||
if (placement_start.is_span()) {
|
||||
result.span = placement_start.span();
|
||||
result.span = placement_start.span().resolved(resolution_context).value();
|
||||
result.start = result.end - result.span;
|
||||
// FIXME: Remove me once have implemented spans overflowing into negative indexes, e.g., grid-row: span 2 / 1
|
||||
if (result.start < 0)
|
||||
|
@ -312,7 +320,7 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
|||
|
||||
if (placement_end.has_identifier()) {
|
||||
auto area_end_line_name = MUST(String::formatted("{}-end", placement_end.identifier()));
|
||||
auto line_number = placement_end.has_line_number() ? placement_end.line_number() : 1;
|
||||
auto line_number = placement_end_line_number.value_or(1);
|
||||
if (auto area_end_line_index = get_nth_line_index_by_line_name(dimension, area_end_line_name, line_number); area_end_line_index.has_value()) {
|
||||
result.end = area_end_line_index.value();
|
||||
} else if (auto line_name_index = get_nth_line_index_by_line_name(dimension, placement_end.identifier(), line_number); line_name_index.has_value()) {
|
||||
|
@ -325,7 +333,7 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
|||
|
||||
if (placement_start.has_identifier()) {
|
||||
auto area_start_line_name = MUST(String::formatted("{}-start", placement_start.identifier()));
|
||||
auto line_number = placement_start.has_line_number() ? placement_start.line_number() : 1;
|
||||
auto line_number = placement_start_line_number.value_or(1);
|
||||
if (auto area_start_line_index = get_nth_line_index_by_line_name(dimension, area_start_line_name, line_number); area_start_line_index.has_value()) {
|
||||
result.start = area_start_line_index.value();
|
||||
} else if (auto line_name_index = get_nth_line_index_by_line_name(dimension, placement_start.identifier(), line_number); line_name_index.has_value()) {
|
||||
|
@ -357,7 +365,7 @@ GridFormattingContext::PlacementPosition GridFormattingContext::resolve_grid_pos
|
|||
// If the placement contains two spans, remove the one contributed by the end grid-placement
|
||||
// property.
|
||||
if (placement_start.is_span() && placement_end.is_span())
|
||||
result.span = placement_start.span();
|
||||
result.span = placement_start.span().resolved(resolution_context).value();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
@ -389,7 +397,7 @@ void GridFormattingContext::place_item_with_row_position(Box const& child_box)
|
|||
|
||||
auto const& grid_column_start = child_box.computed_values().grid_column_start();
|
||||
int column_start = 0;
|
||||
size_t column_span = grid_column_start.is_span() ? grid_column_start.span() : 1;
|
||||
size_t column_span = grid_column_start.is_span() ? grid_column_start.span().resolved({ .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(child_box) }).value() : 1;
|
||||
|
||||
bool found_available_column = false;
|
||||
for (size_t column_index = column_start; column_index < m_occupation_grid.column_count(); column_index++) {
|
||||
|
@ -419,7 +427,7 @@ void GridFormattingContext::place_item_with_column_position(Box const& child_box
|
|||
size_t column_span = placement_position.span;
|
||||
|
||||
auto const& grid_row_start = child_box.computed_values().grid_row_start();
|
||||
size_t row_span = grid_row_start.is_span() ? grid_row_start.span() : 1;
|
||||
size_t row_span = grid_row_start.is_span() ? grid_row_start.span().resolved({ .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(child_box) }).value() : 1;
|
||||
|
||||
// 4.1.1.1. Set the column position of the cursor to the grid item's column-start line. If this is
|
||||
// less than the previous column position of the cursor, increment the row position by 1.
|
||||
|
@ -484,18 +492,20 @@ void GridFormattingContext::place_item_with_no_declared_position(Box const& chil
|
|||
auto const& grid_column_start = computed_values.grid_column_start();
|
||||
auto const& grid_column_end = computed_values.grid_column_end();
|
||||
|
||||
CSS::CalculationResolutionContext resolution_context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(child_box) };
|
||||
|
||||
auto column_start = 0;
|
||||
size_t column_span = 1;
|
||||
if (grid_column_start.is_span())
|
||||
column_span = grid_column_start.span();
|
||||
column_span = grid_column_start.span().resolved(resolution_context).value();
|
||||
else if (grid_column_end.is_span())
|
||||
column_span = grid_column_end.span();
|
||||
column_span = grid_column_end.span().resolved(resolution_context).value();
|
||||
auto row_start = 0;
|
||||
size_t row_span = 1;
|
||||
if (grid_row_start.is_span())
|
||||
row_span = grid_row_start.span();
|
||||
row_span = grid_row_start.span().resolved(resolution_context).value();
|
||||
else if (grid_row_end.is_span())
|
||||
row_span = grid_row_end.span();
|
||||
row_span = grid_row_end.span().resolved(resolution_context).value();
|
||||
|
||||
auto const& auto_flow = grid_container().computed_values().grid_auto_flow();
|
||||
auto dimension = auto_flow.row ? GridDimension::Column : GridDimension::Row;
|
||||
|
@ -1483,11 +1493,13 @@ void GridFormattingContext::place_grid_items()
|
|||
auto const& grid_column_start = child_box->computed_values().grid_column_start();
|
||||
auto const& grid_column_end = child_box->computed_values().grid_column_end();
|
||||
|
||||
CSS::CalculationResolutionContext resolution_context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(child_box) };
|
||||
|
||||
int column_span = 1;
|
||||
if (grid_column_start.is_span())
|
||||
column_span = grid_column_start.span();
|
||||
column_span = grid_column_start.span().resolved(resolution_context).value();
|
||||
else if (grid_column_end.is_span())
|
||||
column_span = grid_column_end.span();
|
||||
column_span = grid_column_end.span().resolved(resolution_context).value();
|
||||
|
||||
if (column_span - 1 > m_occupation_grid.max_column_index())
|
||||
m_occupation_grid.set_max_column_index(column_span - 1);
|
||||
|
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 33 tests
|
||||
|
||||
18 Pass
|
||||
15 Fail
|
||||
24 Pass
|
||||
9 Fail
|
||||
Pass Property grid-area value 'auto / auto / auto / auto'
|
||||
Pass Property grid-row value 'auto / auto'
|
||||
Pass Property grid-column-end value 'auto'
|
||||
|
@ -22,18 +22,18 @@ Pass Property grid-column-end value '5 π_'
|
|||
Fail Property grid-row-start value 'calc(1.1) -a-'
|
||||
Fail Property grid-row-start value 'calc(10) -a-'
|
||||
Fail Property grid-row-start value 'calc(10 + (sign(2cqw - 10px) * 5)) -a-'
|
||||
Fail Property grid-area value 'span 2 i / auto / auto / auto'
|
||||
Pass Property grid-area value 'span 2 i / auto / auto / auto'
|
||||
Pass Property grid-row value 'span 2 / auto'
|
||||
Fail Property grid-column-start value 'span 1 i'
|
||||
Pass Property grid-column-start value 'span 1 i'
|
||||
Pass Property grid-row-start value 'span 1'
|
||||
Fail Property grid-row-end value 'span 2 i'
|
||||
Pass Property grid-row-end value 'span 2 i'
|
||||
Pass Property grid-column-end value 'span 2'
|
||||
Fail Property grid-row-start value 'span i'
|
||||
Fail Property grid-row value 'span i / auto'
|
||||
Pass Property grid-row-start value 'span i'
|
||||
Pass Property grid-row value 'span i / auto'
|
||||
Fail Property grid-area value 'auto / i / auto / i'
|
||||
Fail Property grid-area value 'auto / i / 2 j'
|
||||
Fail Property grid-area value 'auto / i / 2 j / span 3 k'
|
||||
Pass Property grid-row value 'auto / i'
|
||||
Fail Property grid-column value '2 j / span 3 k'
|
||||
Pass Property grid-column value '2 j / span 3 k'
|
||||
Fail Property grid-column-end value '\31st'
|
||||
Fail Property grid-column-end value '\31 st'
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 53 tests
|
||||
|
||||
46 Pass
|
||||
7 Fail
|
||||
48 Pass
|
||||
5 Fail
|
||||
Pass e.style['grid-area'] = "auto" should set grid-column-end
|
||||
Pass e.style['grid-area'] = "auto" should set grid-column-start
|
||||
Pass e.style['grid-area'] = "auto" should set grid-row-end
|
||||
|
@ -54,6 +54,6 @@ Pass e.style['grid-column'] = "5 span" should not set unrelated longhands
|
|||
Pass e.style['grid-column'] = "1 / two" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "1 / two" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "1 / two" should not set unrelated longhands
|
||||
Fail e.style['grid-column'] = "span 1 two / four 3 span" should set grid-column-end
|
||||
Fail e.style['grid-column'] = "span 1 two / four 3 span" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span 1 two / four 3 span" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "span 1 two / four 3 span" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span 1 two / four 3 span" should not set unrelated longhands
|
|
@ -2,8 +2,8 @@ Harness status: OK
|
|||
|
||||
Found 57 tests
|
||||
|
||||
30 Pass
|
||||
27 Fail
|
||||
40 Pass
|
||||
17 Fail
|
||||
Pass e.style['grid-area'] = "auto" should set the property value
|
||||
Pass e.style['grid-area'] = "auto / auto" should set the property value
|
||||
Pass e.style['grid-area'] = "auto / auto / auto" should set the property value
|
||||
|
@ -19,7 +19,7 @@ Pass e.style['grid-row'] = "i / i" should set the property value
|
|||
Pass e.style['grid-row-start'] = "AZ" should set the property value
|
||||
Pass e.style['grid-column-start'] = "-_π" should set the property value
|
||||
Pass e.style['grid-row-end'] = "_9" should set the property value
|
||||
Fail e.style['grid-area'] = "1" should set the property value
|
||||
Pass e.style['grid-area'] = "1" should set the property value
|
||||
Fail e.style['grid-area'] = "+90 -a-" should set the property value
|
||||
Pass e.style['grid-row'] = "az 2" should set the property value
|
||||
Pass e.style['grid-column'] = "9" should set the property value
|
||||
|
@ -31,20 +31,20 @@ Pass e.style['grid-column-start'] = "+90" should set the property value
|
|||
Pass e.style['grid-column-start'] = "Z -44" should set the property value
|
||||
Pass e.style['grid-row-end'] = "1 -πA" should set the property value
|
||||
Pass e.style['grid-column-end'] = "π_ +5" should set the property value
|
||||
Fail e.style['grid-area'] = "span 2 i" should set the property value
|
||||
Fail e.style['grid-area'] = "i 2 SpAn" should set the property value
|
||||
Fail e.style['grid-area'] = "span 1 i" should set the property value
|
||||
Pass e.style['grid-area'] = "span 2 i" should set the property value
|
||||
Pass e.style['grid-area'] = "i 2 SpAn" should set the property value
|
||||
Pass e.style['grid-area'] = "span 1 i" should set the property value
|
||||
Pass e.style['grid-row'] = "span 2" should set the property value
|
||||
Fail e.style['grid-column'] = "i SpAn" should set the property value
|
||||
Fail e.style['grid-row-start'] = "span i" should set the property value
|
||||
Fail e.style['grid-column-start'] = "SpAn i 2" should set the property value
|
||||
Fail e.style['grid-row-end'] = "2 i span" should set the property value
|
||||
Pass e.style['grid-column'] = "i SpAn" should set the property value
|
||||
Pass e.style['grid-row-start'] = "span i" should set the property value
|
||||
Pass e.style['grid-column-start'] = "SpAn i 2" should set the property value
|
||||
Pass e.style['grid-row-end'] = "2 i span" should set the property value
|
||||
Pass e.style['grid-column-end'] = "2 SpAn" should set the property value
|
||||
Fail e.style['grid-area'] = "auto / i" should set the property value
|
||||
Fail e.style['grid-area'] = "auto / i / auto / i" should set the property value
|
||||
Fail e.style['grid-area'] = "auto / i / auto / 2 i" should set the property value
|
||||
Fail e.style['grid-area'] = "1 / i / auto / i" should set the property value
|
||||
Fail e.style['grid-area'] = "1 / auto / auto / auto" should set the property value
|
||||
Pass e.style['grid-area'] = "1 / auto / auto / auto" should set the property value
|
||||
Fail e.style['grid-area'] = "1 / auto / i / auto" should set the property value
|
||||
Pass e.style['grid-area'] = "1 / j / i / k" should set the property value
|
||||
Fail e.style['grid-area'] = "1 / auto / 2 / auto" should set the property value
|
||||
|
@ -57,7 +57,7 @@ Pass e.style['grid-row'] = "auto / i" should set the property value
|
|||
Fail e.style['grid-row'] = "i / auto" should set the property value
|
||||
Pass e.style['grid-row'] = "2 i / auto" should set the property value
|
||||
Pass e.style['grid-row'] = "1 / auto" should set the property value
|
||||
Fail e.style['grid-column'] = "2 j / span 3 k" should set the property value
|
||||
Pass e.style['grid-column'] = "2 j / span 3 k" should set the property value
|
||||
Fail e.style['grid-column-end'] = "\\31st" should set the property value
|
||||
Fail e.style['grid-column-end'] = "\\31 st" should set the property value
|
||||
Fail e.style['grid-column'] = "\\31st / \\31 st" should set the property value
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 16 tests
|
||||
|
||||
12 Pass
|
||||
4 Fail
|
||||
16 Pass
|
||||
Pass Property grid-column value 'auto / auto'
|
||||
Pass Property grid-column value 'auto'
|
||||
Pass Property grid-column value '10 / auto'
|
||||
|
@ -16,7 +15,7 @@ Pass Property grid-column value 'span 2 / auto'
|
|||
Pass Property grid-column value 'span 2'
|
||||
Pass Property grid-column value '2 first / auto'
|
||||
Pass Property grid-column value '2 first'
|
||||
Fail Property grid-column value 'span first / auto'
|
||||
Fail Property grid-column value 'span first'
|
||||
Fail Property grid-column value 'span 2 first / auto'
|
||||
Fail Property grid-column value 'span 2 first'
|
||||
Pass Property grid-column value 'span first / auto'
|
||||
Pass Property grid-column value 'span first'
|
||||
Pass Property grid-column value 'span 2 first / auto'
|
||||
Pass Property grid-column value 'span 2 first'
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 48 tests
|
||||
|
||||
38 Pass
|
||||
10 Fail
|
||||
48 Pass
|
||||
Pass e.style['grid-column'] = "auto / auto" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "auto / auto" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "auto / auto" should not set unrelated longhands
|
||||
|
@ -31,20 +30,20 @@ Pass e.style['grid-column'] = "span 2" should not set unrelated longhands
|
|||
Pass e.style['grid-column'] = "3 last / auto" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "3 last / auto" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "3 last / auto" should not set unrelated longhands
|
||||
Fail e.style['grid-column'] = "3 last" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "3 last" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "3 last" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "3 last" should not set unrelated longhands
|
||||
Fail e.style['grid-column'] = "span first / auto" should set grid-column-end
|
||||
Fail e.style['grid-column'] = "span first / auto" should set grid-column-start
|
||||
Fail e.style['grid-column'] = "span first / auto" should not set unrelated longhands
|
||||
Fail e.style['grid-column'] = "span first" should set grid-column-end
|
||||
Fail e.style['grid-column'] = "span first" should set grid-column-start
|
||||
Fail e.style['grid-column'] = "span first" should not set unrelated longhands
|
||||
Pass e.style['grid-column'] = "span first / auto" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "span first / auto" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span first / auto" should not set unrelated longhands
|
||||
Pass e.style['grid-column'] = "span first" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "span first" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span first" should not set unrelated longhands
|
||||
Pass e.style['grid-column'] = "span 2 first / auto" should set grid-column-end
|
||||
Fail e.style['grid-column'] = "span 2 first / auto" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span 2 first / auto" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span 2 first / auto" should not set unrelated longhands
|
||||
Fail e.style['grid-column'] = "span 2 first" should set grid-column-end
|
||||
Fail e.style['grid-column'] = "span 2 first" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span 2 first" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "span 2 first" should set grid-column-start
|
||||
Pass e.style['grid-column'] = "span 2 first" should not set unrelated longhands
|
||||
Pass e.style['grid-column'] = "last / last" should set grid-column-end
|
||||
Pass e.style['grid-column'] = "last / last" should set grid-column-start
|
||||
|
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 15 tests
|
||||
|
||||
11 Pass
|
||||
4 Fail
|
||||
15 Pass
|
||||
Pass Property grid-row value 'auto / auto'
|
||||
Pass Property grid-row value 'auto'
|
||||
Pass Property grid-row value '10 / auto'
|
||||
|
@ -14,8 +13,8 @@ Pass Property grid-row value 'span 2 / auto'
|
|||
Pass Property grid-row value 'span 2'
|
||||
Pass Property grid-row value '3 last / auto'
|
||||
Pass Property grid-row value '3 last'
|
||||
Fail Property grid-row value 'span first / auto'
|
||||
Fail Property grid-row value 'span first'
|
||||
Fail Property grid-row value 'span 2 first / auto'
|
||||
Fail Property grid-row value 'span 2 first'
|
||||
Pass Property grid-row value 'span first / auto'
|
||||
Pass Property grid-row value 'span first'
|
||||
Pass Property grid-row value 'span 2 first / auto'
|
||||
Pass Property grid-row value 'span 2 first'
|
||||
Pass Property grid-row value 'last / last'
|
|
@ -2,8 +2,7 @@ Harness status: OK
|
|||
|
||||
Found 48 tests
|
||||
|
||||
38 Pass
|
||||
10 Fail
|
||||
48 Pass
|
||||
Pass e.style['grid-row'] = "auto / auto" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "auto / auto" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "auto / auto" should not set unrelated longhands
|
||||
|
@ -31,20 +30,20 @@ Pass e.style['grid-row'] = "span 2" should not set unrelated longhands
|
|||
Pass e.style['grid-row'] = "3 last / auto" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "3 last / auto" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "3 last / auto" should not set unrelated longhands
|
||||
Fail e.style['grid-row'] = "3 last" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "3 last" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "3 last" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "3 last" should not set unrelated longhands
|
||||
Fail e.style['grid-row'] = "span first / auto" should set grid-row-end
|
||||
Fail e.style['grid-row'] = "span first / auto" should set grid-row-start
|
||||
Fail e.style['grid-row'] = "span first / auto" should not set unrelated longhands
|
||||
Fail e.style['grid-row'] = "span first" should set grid-row-end
|
||||
Fail e.style['grid-row'] = "span first" should set grid-row-start
|
||||
Fail e.style['grid-row'] = "span first" should not set unrelated longhands
|
||||
Pass e.style['grid-row'] = "span first / auto" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "span first / auto" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "span first / auto" should not set unrelated longhands
|
||||
Pass e.style['grid-row'] = "span first" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "span first" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "span first" should not set unrelated longhands
|
||||
Pass e.style['grid-row'] = "span 2 first / auto" should set grid-row-end
|
||||
Fail e.style['grid-row'] = "span 2 first / auto" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "span 2 first / auto" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "span 2 first / auto" should not set unrelated longhands
|
||||
Fail e.style['grid-row'] = "span 2 first" should set grid-row-end
|
||||
Fail e.style['grid-row'] = "span 2 first" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "span 2 first" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "span 2 first" should set grid-row-start
|
||||
Pass e.style['grid-row'] = "span 2 first" should not set unrelated longhands
|
||||
Pass e.style['grid-row'] = "last / last" should set grid-row-end
|
||||
Pass e.style['grid-row'] = "last / last" should set grid-row-start
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue