From 66ea341a61cabdf2c913857d0726e8bbaa7c9a5a Mon Sep 17 00:00:00 2001 From: Gingeh <39150378+Gingeh@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:15:04 +1100 Subject: [PATCH 1/2] LibWeb: Move CSS character type definitions to new header --- Libraries/LibWeb/CSS/CharacterTypes.h | 73 ++++++++++++++++++++++ Libraries/LibWeb/CSS/Parser/Tokenizer.cpp | 74 ++++++----------------- 2 files changed, 90 insertions(+), 57 deletions(-) create mode 100644 Libraries/LibWeb/CSS/CharacterTypes.h diff --git a/Libraries/LibWeb/CSS/CharacterTypes.h b/Libraries/LibWeb/CSS/CharacterTypes.h new file mode 100644 index 00000000000..7525554134a --- /dev/null +++ b/Libraries/LibWeb/CSS/CharacterTypes.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2024, the Ladybird developers. + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::CSS { + +// https://www.w3.org/TR/css-syntax-3/#digit +constexpr bool is_digit(u32 code_point) +{ + // A code point between U+0030 DIGIT ZERO (0) and U+0039 DIGIT NINE (9) inclusive. + return code_point >= 0x30 && code_point <= 0x39; +} + +// https://www.w3.org/TR/css-syntax-3/#hex-digit +constexpr bool is_hex_digit(u32 code_point) +{ + // A digit, + // or a code point between U+0041 LATIN CAPITAL LETTER A (A) and U+0046 LATIN CAPITAL LETTER F (F) inclusive, + // or a code point between U+0061 LATIN SMALL LETTER A (a) and U+0066 LATIN SMALL LETTER F (f) inclusive. + return is_digit(code_point) || (code_point >= 0x41 && code_point <= 0x46) || (code_point >= 0x61 && code_point <= 0x66); +} + +// https://www.w3.org/TR/css-syntax-3/#ident-start-code-point +constexpr bool is_ident_start_code_point(u32 code_point) +{ + // A letter, a non-ASCII code point, or U+005F LOW LINE (_). + // Note: the is_unicode condition is used to reject the Tokenizer's EOF codepoint. + return is_ascii_alpha(code_point) || (!is_ascii(code_point) && is_unicode(code_point)) || code_point == '_'; +} + +// https://www.w3.org/TR/css-syntax-3/#ident-code-point +constexpr bool is_ident_code_point(u32 code_point) +{ + // An ident-start code point, a digit, or U+002D HYPHEN-MINUS (-). + return is_ident_start_code_point(code_point) || is_ascii_digit(code_point) || code_point == '-'; +} + +// https://www.w3.org/TR/css-syntax-3/#non-printable-code-point +constexpr bool is_non_printable_code_point(u32 code_point) +{ + return code_point <= 0x8 || code_point == 0xB || (code_point >= 0xE && code_point <= 0x1F) || code_point == 0x7F; +} + +// https://www.w3.org/TR/css-syntax-3/#newline +constexpr inline bool is_newline(u32 code_point) +{ + // U+000A LINE FEED. + // Note that U+000D CARRIAGE RETURN and U+000C FORM FEED are not included in this definition, + // as they are converted to U+000A LINE FEED during preprocessing. + return code_point == 0xA; +} + +// https://www.w3.org/TR/css-syntax-3/#whitespace +constexpr bool is_whitespace(u32 code_point) +{ + // A newline, U+0009 CHARACTER TABULATION, or U+0020 SPACE. + return is_newline(code_point) || code_point == '\t' || code_point == ' '; +} + +// https://www.w3.org/TR/css-syntax-3/#maximum-allowed-code-point +constexpr bool is_greater_than_maximum_allowed_code_point(u32 code_point) +{ + // The greatest code point defined by Unicode: U+10FFFF. + return code_point > 0x10FFFF; +} +} diff --git a/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp b/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp index 443fc93af50..229a4e2e1de 100644 --- a/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp +++ b/Libraries/LibWeb/CSS/Parser/Tokenizer.cpp @@ -5,12 +5,12 @@ * SPDX-License-Identifier: BSD-2-Clause */ -#include #include #include #include #include #include +#include #include #include @@ -35,41 +35,11 @@ static inline bool is_quotation_mark(u32 code_point) return code_point == 0x22; } -static inline bool is_greater_than_maximum_allowed_code_point(u32 code_point) -{ - return code_point > 0x10FFFF; -} - -static inline bool is_low_line(u32 code_point) -{ - return code_point == 0x5F; -} - -// https://www.w3.org/TR/css-syntax-3/#ident-start-code-point -static inline bool is_ident_start_code_point(u32 code_point) -{ - // FIXME: We use !is_ascii() for "non-ASCII code point" in the spec, but it's not quite right - - // it treats EOF as a valid! The spec also lacks a definition of code point. For now, the - // !is_eof() check is a hack, but it should work. - return !is_eof(code_point) && (is_ascii_alpha(code_point) || !is_ascii(code_point) || is_low_line(code_point)); -} - static inline bool is_hyphen_minus(u32 code_point) { return code_point == 0x2D; } -// https://www.w3.org/TR/css-syntax-3/#ident-code-point -static inline bool is_ident_code_point(u32 code_point) -{ - return is_ident_start_code_point(code_point) || is_ascii_digit(code_point) || is_hyphen_minus(code_point); -} - -static inline bool is_non_printable(u32 code_point) -{ - return code_point <= 0x8 || code_point == 0xB || (code_point >= 0xE && code_point <= 0x1F) || code_point == 0x7F; -} - static inline bool is_number_sign(u32 code_point) { return code_point == 0x23; @@ -110,11 +80,6 @@ static inline bool is_full_stop(u32 code_point) return code_point == 0x2E; } -static inline bool is_newline(u32 code_point) -{ - return code_point == 0xA; -} - static inline bool is_asterisk(u32 code_point) { return code_point == 0x2A; @@ -170,11 +135,6 @@ static inline bool is_closed_curly_bracket(u32 code_point) return code_point == 0x7D; } -static inline bool is_whitespace(u32 code_point) -{ - return code_point == 0x9 || code_point == 0xA || code_point == 0x20; -} - static inline bool is_percent(u32 code_point) { return code_point == 0x25; @@ -400,14 +360,14 @@ u32 Tokenizer::consume_escaped_code_point() auto input = next_code_point(); // hex digit - if (is_ascii_hex_digit(input)) { + if (is_hex_digit(input)) { // Consume as many hex digits as possible, but no more than 5. // Note that this means 1-6 hex digits have been consumed in total. StringBuilder builder; builder.append_code_point(input); size_t counter = 0; - while (is_ascii_hex_digit(peek_code_point()) && counter++ < 5) { + while (is_hex_digit(peek_code_point()) && counter++ < 5) { builder.append_code_point(next_code_point()); } @@ -517,7 +477,7 @@ Number Tokenizer::consume_a_number() // 3. While the next input code point is a digit, consume it and append it to repr. for (;;) { auto digits = peek_code_point(); - if (!is_ascii_digit(digits)) + if (!is_digit(digits)) break; repr.append_code_point(next_code_point()); @@ -525,7 +485,7 @@ Number Tokenizer::consume_a_number() // 4. If the next 2 input code points are U+002E FULL STOP (.) followed by a digit, then: auto maybe_number = peek_twin(); - if (is_full_stop(maybe_number.first) && is_ascii_digit(maybe_number.second)) { + if (is_full_stop(maybe_number.first) && is_digit(maybe_number.second)) { // 1. Consume them. // 2. Append them to repr. repr.append_code_point(next_code_point()); @@ -537,7 +497,7 @@ Number Tokenizer::consume_a_number() // 4. While the next input code point is a digit, consume it and append it to repr. for (;;) { auto digit = peek_code_point(); - if (!is_ascii_digit(digit)) + if (!is_digit(digit)) break; repr.append_code_point(next_code_point()); @@ -549,17 +509,17 @@ Number Tokenizer::consume_a_number() // or U+002B PLUS SIGN (+), followed by a digit, then: auto maybe_exp = peek_triplet(); if ((is_E(maybe_exp.first) || is_e(maybe_exp.first)) - && (((is_plus_sign(maybe_exp.second) || is_hyphen_minus(maybe_exp.second)) && is_ascii_digit(maybe_exp.third)) - || (is_ascii_digit(maybe_exp.second)))) { + && (((is_plus_sign(maybe_exp.second) || is_hyphen_minus(maybe_exp.second)) && is_digit(maybe_exp.third)) + || (is_digit(maybe_exp.second)))) { // 1. Consume them. // 2. Append them to repr. if (is_plus_sign(maybe_exp.second) || is_hyphen_minus(maybe_exp.second)) { - if (is_ascii_digit(maybe_exp.third)) { + if (is_digit(maybe_exp.third)) { repr.append_code_point(next_code_point()); repr.append_code_point(next_code_point()); repr.append_code_point(next_code_point()); } - } else if (is_ascii_digit(maybe_exp.second)) { + } else if (is_digit(maybe_exp.second)) { repr.append_code_point(next_code_point()); repr.append_code_point(next_code_point()); } @@ -570,7 +530,7 @@ Number Tokenizer::consume_a_number() // 4. While the next input code point is a digit, consume it and append it to repr. for (;;) { auto digits = peek_code_point(); - if (!is_ascii_digit(digits)) + if (!is_digit(digits)) break; repr.append_code_point(next_code_point()); @@ -713,7 +673,7 @@ Token Tokenizer::consume_a_url_token() // U+0027 APOSTROPHE (') // U+0028 LEFT PARENTHESIS (() // non-printable code point - if (is_quotation_mark(input) || is_apostrophe(input) || is_left_paren(input) || is_non_printable(input)) { + if (is_quotation_mark(input) || is_apostrophe(input) || is_left_paren(input) || is_non_printable_code_point(input)) { // This is a parse error. Consume the remnants of a bad url, create a , and return it. log_parse_error(); consume_the_remnants_of_a_bad_url(); @@ -855,12 +815,12 @@ bool Tokenizer::would_start_a_number(U32Triplet values) // U+002D HYPHEN-MINUS (-) if (is_plus_sign(values.first) || is_hyphen_minus(values.first)) { // If the second code point is a digit, return true. - if (is_ascii_digit(values.second)) + if (is_digit(values.second)) return true; // Otherwise, if the second code point is a U+002E FULL STOP (.) and the third // code point is a digit, return true. - if (is_full_stop(values.second) && is_ascii_digit(values.third)) + if (is_full_stop(values.second) && is_digit(values.third)) return true; // Otherwise, return false. @@ -870,10 +830,10 @@ bool Tokenizer::would_start_a_number(U32Triplet values) // U+002E FULL STOP (.) if (is_full_stop(values.first)) // If the second code point is a digit, return true. Otherwise, return false. - return is_ascii_digit(values.second); + return is_digit(values.second); // digit - if (is_ascii_digit(values.first)) + if (is_digit(values.first)) // Return true. return true; @@ -1328,7 +1288,7 @@ Token Tokenizer::consume_a_token() } // digit - if (is_ascii_digit(input)) { + if (is_digit(input)) { dbgln_if(CSS_TOKENIZER_DEBUG, "is digit"); // Reconsume the current input code point, consume a numeric token, and return it. reconsume_current_input_code_point(); From 7fe49734d7f87412e6b6a3aecf5e52c4a30ad138 Mon Sep 17 00:00:00 2001 From: Gingeh <39150378+Gingeh@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:16:03 +1100 Subject: [PATCH 2/2] LibWeb: Improve grid-template-area parsing and serialization --- Libraries/LibWeb/CSS/Parser/Parser.cpp | 53 ++++++++++++-- .../GridTemplateAreaStyleValue.cpp | 13 ++-- .../grid-support-grid-template-areas-001.txt | 56 +++++++++++++++ .../parsing/grid-shorthand-serialization.txt | 14 ++-- .../css/css-grid/parsing/grid-shorthand.txt | 10 +-- .../parsing/grid-template-areas-computed.txt | 19 +++-- .../parsing/grid-template-areas-invalid.txt | 13 ++-- .../parsing/grid-template-areas-one-cell.txt | 7 +- .../parsing/grid-template-areas-valid.txt | 19 +++-- .../parsing/grid-template-shorthand.txt | 10 +-- .../grid-support-grid-template-areas-001.html | 72 +++++++++++++++++++ .../grid-definition/support/testing-utils.js | 43 +++++++++++ 12 files changed, 270 insertions(+), 59 deletions(-) create mode 100644 Tests/LibWeb/Text/expected/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.txt create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.html create mode 100644 Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/support/testing-utils.js diff --git a/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Libraries/LibWeb/CSS/Parser/Parser.cpp index 5d8ff1db63e..77f3975998c 100644 --- a/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -7585,20 +7586,60 @@ RefPtr Parser::parse_grid_shorthand_value(TokenStream Parser::parse_grid_template_areas_value(TokenStream& tokens) { // none | + - Vector> grid_area_rows; - if (auto none = parse_all_as_single_keyword_value(tokens, Keyword::None)) - return GridTemplateAreaStyleValue::create(move(grid_area_rows)); + return GridTemplateAreaStyleValue::create({}); + + auto is_full_stop = [](u32 code_point) { + return code_point == '.'; + }; + + auto consume_while = [](Utf8CodePointIterator& code_points, AK::Function predicate) { + StringBuilder builder; + while (!code_points.done() && predicate(*code_points)) { + builder.append_code_point(*code_points); + ++code_points; + } + return MUST(builder.to_string()); + }; + + Vector> grid_area_rows; + Optional column_count; auto transaction = tokens.begin_transaction(); while (tokens.has_next_token() && tokens.next_token().is(Token::Type::String)) { Vector grid_area_columns; - auto const parts = MUST(tokens.consume_a_token().token().string().to_string().split(' ')); - for (auto& part : parts) { - grid_area_columns.append(part); + auto string = tokens.consume_a_token().token().string().code_points(); + auto code_points = string.begin(); + + while (!code_points.done()) { + if (is_whitespace(*code_points)) { + consume_while(code_points, is_whitespace); + } else if (is_full_stop(*code_points)) { + consume_while(code_points, *is_full_stop); + grid_area_columns.append("."_string); + } else if (is_ident_code_point(*code_points)) { + auto token = consume_while(code_points, is_ident_code_point); + grid_area_columns.append(move(token)); + } else { + return nullptr; + } } + + if (grid_area_columns.is_empty()) + return nullptr; + + if (column_count.has_value()) { + if (grid_area_columns.size() != column_count) + return nullptr; + } else { + column_count = grid_area_columns.size(); + } + grid_area_rows.append(move(grid_area_columns)); } + + // FIXME: If a named grid area spans multiple grid cells, but those cells do not form a single filled-in rectangle, the declaration is invalid. + transaction.commit(); return GridTemplateAreaStyleValue::create(grid_area_rows); } diff --git a/Libraries/LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.cpp index 45c3d93acbc..b03d906fb16 100644 --- a/Libraries/LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.cpp @@ -8,6 +8,7 @@ */ #include "GridTemplateAreaStyleValue.h" +#include namespace Web::CSS { @@ -23,13 +24,15 @@ String GridTemplateAreaStyleValue::to_string() const StringBuilder builder; for (size_t y = 0; y < m_grid_template_area.size(); ++y) { + if (y != 0) + builder.append(' '); + StringBuilder row_builder; for (size_t x = 0; x < m_grid_template_area[y].size(); ++x) { - builder.appendff("{}", m_grid_template_area[y][x]); - if (x < m_grid_template_area[y].size() - 1) - builder.append(" "sv); + if (x != 0) + row_builder.append(' '); + row_builder.appendff("{}", m_grid_template_area[y][x]); } - if (y < m_grid_template_area.size() - 1) - builder.append(", "sv); + serialize_a_string(builder, row_builder.string_view()); } return MUST(builder.to_string()); } diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.txt new file mode 100644 index 00000000000..033e914fb4d --- /dev/null +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.txt @@ -0,0 +1,56 @@ +Summary + +Harness status: OK + +Rerun + +Found 45 tests + +36 Pass +9 Fail +Details +Result Test Name MessagePass 'grid' with: grid-template-areas: none; +Pass 'grid' with: grid-template-areas: "a"; +Pass 'grid' with: grid-template-areas: "."; +Pass 'grid' with: grid-template-areas: "lower UPPER 10 -minus _low 1-st ©copy_right line¶"; +Pass 'grid' with: grid-template-areas: "a b"; +Pass 'grid' with: grid-template-areas: "a b" "c d"; +Pass 'grid' with: grid-template-areas: "a b" "c d"; +Pass 'grid' with: grid-template-areas: "a b""c d"; +Pass 'grid' with: grid-template-areas: "a b" "c d"; +Pass 'grid' with: grid-template-areas: "a b" "c d"; +Pass 'grid' with: grid-template-areas: "a b" "a b"; +Pass 'grid' with: grid-template-areas: "a a" "b b"; +Pass 'grid' with: grid-template-areas: ". a ." "b a c"; +Pass 'grid' with: grid-template-areas: ".. a ..." "b a c"; +Pass 'grid' with: grid-template-areas: ".a..." "b a c"; +Pass 'grid' with: grid-template-areas: "head head" "nav main" "foot ."; +Pass 'grid' with: grid-template-areas: "head head" "nav main" "foot ...."; +Pass 'grid' with: grid-template-areas: "head head" "nav main" "foot."; +Pass 'grid' with: grid-template-areas: ". header header ." "nav main main main" "nav footer footer ."; +Pass 'grid' with: grid-template-areas: "... header header ...." "nav main main main" "nav footer footer ...."; +Pass 'grid' with: grid-template-areas: "...header header...." "nav main main main" "nav footer footer...."; +Pass 'grid' with: grid-template-areas: "title stats" "score stats" "board board" "ctrls ctrls"; +Pass 'grid' with: grid-template-areas: "title board" "stats board" "score ctrls"; +Pass 'grid' with: grid-template-areas: ". a" "b a" ". a"; +Pass 'grid' with: grid-template-areas: ".. a" "b a" "... a"; +Pass 'grid' with: grid-template-areas: "..a" "b a" ".a"; +Pass 'grid' with: grid-template-areas: "a a a" "b b b"; +Pass 'grid' with: grid-template-areas: ". ." "a a"; +Pass 'grid' with: grid-template-areas: "... ...." "a a"; +Pass 'grid' with: grid-template-areas: a; +Pass 'grid' with: grid-template-areas: "a" "b c"; +Pass 'grid' with: grid-template-areas: "a b" "c" "d e"; +Pass 'grid' with: grid-template-areas: "a b c" "d e"; +Pass 'grid' with: grid-template-areas: "a b"-"c d"; +Pass 'grid' with: grid-template-areas: "a b" - "c d"; +Pass 'grid' with: grid-template-areas: "a b" . "c d"; +Fail 'grid' with: grid-template-areas: "a b a"; +Fail 'grid' with: grid-template-areas: "a" "b" "a"; +Fail 'grid' with: grid-template-areas: "a b" "b b"; +Fail 'grid' with: grid-template-areas: "b a" "b b"; +Fail 'grid' with: grid-template-areas: "a b" "b a"; +Fail 'grid' with: grid-template-areas: "a ." ". a"; +Fail 'grid' with: grid-template-areas: ","; +Fail 'grid' with: grid-template-areas: "10%"; +Fail 'grid' with: grid-template-areas: "USD$"; \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand-serialization.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand-serialization.txt index 539aff1f5d8..6cce9dd8d70 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand-serialization.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand-serialization.txt @@ -6,15 +6,15 @@ Rerun Found 121 tests -26 Pass -95 Fail +31 Pass +90 Fail Details Result Test Name MessageFail e.style.cssText = grid: auto-flow auto / 100px 100px should set grid Fail e.style.cssText = grid: auto-flow auto / 100px 100px should set grid-template-areas Pass e.style.cssText = grid: auto-flow auto / 100px 100px; grid-template-areas: "one two" "three four" should set grid Fail e.style.cssText = grid: auto-flow auto / 100px 100px; grid-template-areas: "one two" "three four" should set grid-auto-flow Fail e.style.cssText = grid: auto-flow auto / 100px 100px; grid-template-areas: "one two" "three four" should set grid-auto-rows -Fail e.style.cssText = grid: auto-flow auto / 100px 100px; grid-template-areas: "one two" "three four" should set grid-template-areas +Pass e.style.cssText = grid: auto-flow auto / 100px 100px; grid-template-areas: "one two" "three four" should set grid-template-areas Fail e.style.cssText = grid: 30px 40px / 50px 60px; grid-auto-flow: column should set grid Pass e.style.cssText = grid: 30px 40px / 50px 60px; grid-auto-flow: column should set grid-auto-flow Fail e.style.cssText = grid: 30px 40px / 50px 60px; grid-auto-flow: column should set grid-template @@ -115,18 +115,18 @@ Fail e.style.cssText = grid: auto-flow 1px / none; grid-template-rows: repeat(au Fail e.style.cssText = grid: auto-flow 1px / none; grid-template-rows: repeat(auto-fit, 3px) should set grid-template-columns Fail e.style.cssText = grid: auto-flow 1px / none; grid-template-rows: repeat(auto-fit, 3px) should set grid-template-rows Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 3px); grid-template-areas: "one two" "three four" should set grid -Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 3px); grid-template-areas: "one two" "three four" should set grid-template-areas +Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 3px); grid-template-areas: "one two" "three four" should set grid-template-areas Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 3px); grid-template-areas: "one two" "three four" should set grid-template-columns Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 3px); grid-template-areas: "one two" "three four" should set grid-template-rows Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 1fr); grid-template-areas: "one two" "three four" should set grid -Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 1fr); grid-template-areas: "one two" "three four" should set grid-template-areas +Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 1fr); grid-template-areas: "one two" "three four" should set grid-template-areas Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 1fr); grid-template-areas: "one two" "three four" should set grid-template-columns Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(2, 1fr); grid-template-areas: "one two" "three four" should set grid-template-rows Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fill, 3px); grid-template-areas: "one two" "three four" should set grid -Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fill, 3px); grid-template-areas: "one two" "three four" should set grid-template-areas +Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fill, 3px); grid-template-areas: "one two" "three four" should set grid-template-areas Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fill, 3px); grid-template-areas: "one two" "three four" should set grid-template-columns Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fill, 3px); grid-template-areas: "one two" "three four" should set grid-template-rows Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fit, 3px); grid-template-areas: "one two" "three four" should set grid -Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fit, 3px); grid-template-areas: "one two" "three four" should set grid-template-areas +Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fit, 3px); grid-template-areas: "one two" "three four" should set grid-template-areas Fail e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fit, 3px); grid-template-areas: "one two" "three four" should set grid-template-columns Pass e.style.cssText = grid-template-rows: auto auto; grid-template-columns: repeat(auto-fit, 3px); grid-template-areas: "one two" "three four" should set grid-template-rows \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand.txt index 244054a5e56..9e837dc030a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-shorthand.txt @@ -6,8 +6,8 @@ Rerun Found 63 tests -18 Pass -45 Fail +21 Pass +42 Fail Details Result Test Name MessageFail e.style['grid'] = "none" should set grid-auto-columns Fail e.style['grid'] = "none" should set grid-auto-flow @@ -40,21 +40,21 @@ Pass e.style['grid'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5e Fail e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-auto-columns Fail e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-auto-flow Fail e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-auto-rows -Fail e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-areas +Pass e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-areas Pass e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-columns Fail e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-rows Pass e.style['grid'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should not set unrelated longhands Fail e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-auto-columns Fail e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-auto-flow Fail e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-auto-rows -Fail e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-areas +Pass e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-areas Pass e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-columns Fail e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-rows Pass e.style['grid'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should not set unrelated longhands Fail e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-auto-columns Fail e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-auto-flow Fail e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-auto-rows -Fail e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-areas +Pass e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-areas Fail e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-columns Fail e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-rows Pass e.style['grid'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should not set unrelated longhands diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-computed.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-computed.txt index bc33dae34ee..da06f7e9487 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-computed.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-computed.txt @@ -6,15 +6,14 @@ Rerun Found 9 tests -1 Pass -8 Fail +9 Pass Details Result Test Name MessagePass Property grid-template-areas value 'none' -Fail Property grid-template-areas value '"first"' -Fail Property grid-template-areas value '"first second"' -Fail Property grid-template-areas value '"1st 2nd 3rd"' -Fail Property grid-template-areas value '"first second" "third fourth"' -Fail Property grid-template-areas value '"first second" "third ." "1st 2nd" "3rd 4th"' -Fail Property grid-template-areas value '" a b "' -Fail Property grid-template-areas value '"c d"' -Fail Property grid-template-areas value '"first ..."' \ No newline at end of file +Pass Property grid-template-areas value '"first"' +Pass Property grid-template-areas value '"first second"' +Pass Property grid-template-areas value '"1st 2nd 3rd"' +Pass Property grid-template-areas value '"first second" "third fourth"' +Pass Property grid-template-areas value '"first second" "third ." "1st 2nd" "3rd 4th"' +Pass Property grid-template-areas value '" a b "' +Pass Property grid-template-areas value '"c d"' +Pass Property grid-template-areas value '"first ..."' \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-invalid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-invalid.txt index 712731830d8..c8c2ff0766a 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-invalid.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-invalid.txt @@ -6,17 +6,16 @@ Rerun Found 11 tests -6 Pass -5 Fail +11 Pass Details Result Test Name MessagePass e.style['grid-template-areas'] = "auto" should not set the property value Pass e.style['grid-template-areas'] = "none \"first\"" should not set the property value Pass e.style['grid-template-areas'] = "\"first\" none" should not set the property value Pass e.style['grid-template-areas'] = "\"\"" should not set the property value Pass e.style['grid-template-areas'] = "\" \"" should not set the property value -Fail e.style['grid-template-areas'] = "\".\" \"\"" should not set the property value -Fail e.style['grid-template-areas'] = "\".\" \" \"" should not set the property value -Fail e.style['grid-template-areas'] = "\"first\" \"\"" should not set the property value -Fail e.style['grid-template-areas'] = "\"first\" \"\" \"second\"" should not set the property value -Fail e.style['grid-template-areas'] = "\"first\" \" \"" should not set the property value +Pass e.style['grid-template-areas'] = "\".\" \"\"" should not set the property value +Pass e.style['grid-template-areas'] = "\".\" \" \"" should not set the property value +Pass e.style['grid-template-areas'] = "\"first\" \"\"" should not set the property value +Pass e.style['grid-template-areas'] = "\"first\" \"\" \"second\"" should not set the property value +Pass e.style['grid-template-areas'] = "\"first\" \" \"" should not set the property value Pass e.style['grid-template-areas'] = "\"\" none" should not set the property value \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-one-cell.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-one-cell.txt index 1b94117a6e2..171f45f77f1 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-one-cell.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-one-cell.txt @@ -6,12 +6,11 @@ Rerun Found 6 tests -4 Pass -2 Fail +6 Pass Details Result Test Name MessagePass "grid-template-areas: 'a';" should be valid. Pass "grid-template-areas: '.';" should be valid. Pass "grid-template-areas: '';" should be invalid. -Fail "grid-template-areas: '' '';" should be invalid. -Fail "grid-template-areas: '$';" should be invalid. +Pass "grid-template-areas: '' '';" should be invalid. +Pass "grid-template-areas: '$';" should be invalid. Pass "grid-template-areas: ' ';" should be invalid. \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-valid.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-valid.txt index 64240754036..121a67811b3 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-valid.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-areas-valid.txt @@ -6,15 +6,14 @@ Rerun Found 9 tests -1 Pass -8 Fail +9 Pass Details Result Test Name MessagePass e.style['grid-template-areas'] = "none" should set the property value -Fail e.style['grid-template-areas'] = "\"first\"" should set the property value -Fail e.style['grid-template-areas'] = "\"first second\"" should set the property value -Fail e.style['grid-template-areas'] = "\"1st 2nd 3rd\"" should set the property value -Fail e.style['grid-template-areas'] = "\"first second\" \"third fourth\"" should set the property value -Fail e.style['grid-template-areas'] = "\"first second\" \"third .\" \"1st 2nd\" \"3rd 4th\"" should set the property value -Fail e.style['grid-template-areas'] = "\" a \t b \"" should set the property value -Fail e.style['grid-template-areas'] = "\"c\td\"" should set the property value -Fail e.style['grid-template-areas'] = "\"first ...\"" should set the property value \ No newline at end of file +Pass e.style['grid-template-areas'] = "\"first\"" should set the property value +Pass e.style['grid-template-areas'] = "\"first second\"" should set the property value +Pass e.style['grid-template-areas'] = "\"1st 2nd 3rd\"" should set the property value +Pass e.style['grid-template-areas'] = "\"first second\" \"third fourth\"" should set the property value +Pass e.style['grid-template-areas'] = "\"first second\" \"third .\" \"1st 2nd\" \"3rd 4th\"" should set the property value +Pass e.style['grid-template-areas'] = "\" a \t b \"" should set the property value +Pass e.style['grid-template-areas'] = "\"c\td\"" should set the property value +Pass e.style['grid-template-areas'] = "\"first ...\"" should set the property value \ No newline at end of file diff --git a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-shorthand.txt b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-shorthand.txt index 96f5e9283bc..0ae2c86917b 100644 --- a/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-shorthand.txt +++ b/Tests/LibWeb/Text/expected/wpt-import/css/css-grid/parsing/grid-template-shorthand.txt @@ -6,8 +6,8 @@ Rerun Found 24 tests -15 Pass -9 Fail +18 Pass +6 Fail Details Result Test Name MessagePass e.style['grid-template'] = "none" should set grid-template-areas Fail e.style['grid-template'] = "none" should set grid-template-columns @@ -21,15 +21,15 @@ Pass e.style['grid-template'] = "fit-content(calc(-0.5em + 10px)) / fit-content( Pass e.style['grid-template'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-template-columns Pass e.style['grid-template'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should set grid-template-rows Pass e.style['grid-template'] = "fit-content(calc(-0.5em + 10px)) / fit-content(calc(0.5em + 10px))" should not set unrelated longhands -Fail e.style['grid-template'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-areas +Pass e.style['grid-template'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-areas Pass e.style['grid-template'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-columns Fail e.style['grid-template'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should set grid-template-rows Pass e.style['grid-template'] = "[header-top] \"a a a\" [header-bottom] [main-top] \"b b b\" 1fr [main-bottom] / auto 1fr auto" should not set unrelated longhands -Fail e.style['grid-template'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-areas +Pass e.style['grid-template'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-areas Pass e.style['grid-template'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-columns Fail e.style['grid-template'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should set grid-template-rows Pass e.style['grid-template'] = " \"a a a\" \"b b b\" 1fr/ auto 1fr auto" should not set unrelated longhands -Fail e.style['grid-template'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-areas +Pass e.style['grid-template'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-areas Fail e.style['grid-template'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-columns Fail e.style['grid-template'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should set grid-template-rows Pass e.style['grid-template'] = " [] \"a a a\" [] [] \"b b b\" 1fr [] / [] auto 1fr [] auto []" should not set unrelated longhands \ No newline at end of file diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.html b/Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.html new file mode 100644 index 00000000000..82ecaf89ad1 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/grid-support-grid-template-areas-001.html @@ -0,0 +1,72 @@ + + +CSS Grid Layout Test: Support for 'grid-template-ares' property + + + + + + + + +
+ +
+ + diff --git a/Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/support/testing-utils.js b/Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/support/testing-utils.js new file mode 100644 index 00000000000..30b944265b4 --- /dev/null +++ b/Tests/LibWeb/Text/input/wpt-import/css/css-grid/grid-definition/support/testing-utils.js @@ -0,0 +1,43 @@ +var TestingUtils = (function() { + + function checkGridTemplateColumns(element, value) { + if (!Array.isArray(value)) + value = new Array(value); + assert_in_array(getComputedStyle(element).gridTemplateColumns, value, "gridTemplateColumns"); + } + + function checkGridTemplateRows(element, value) { + if (!Array.isArray(value)) + value = new Array(value); + assert_in_array(getComputedStyle(element).gridTemplateRows, value, "gridTemplateRows"); + } + + function testGridTemplateColumnsRows(gridId, columnsStyle, rowsStyle, columnsComputedValue, rowsComputedValue, label) { + test(function() { + var grid = document.getElementById(gridId); + grid.style.gridTemplateColumns = columnsStyle; + grid.style.gridTemplateRows = rowsStyle; + checkGridTemplateColumns(grid, columnsComputedValue); + checkGridTemplateRows(grid, rowsComputedValue); + }, (label ? label + " " : "") + "'" + gridId + "' with: grid-template-columns: " + columnsStyle + "; and grid-template-rows: " + rowsStyle + ";"); + } + + function checkGridTemplateAreas(element, value) { + if (!Array.isArray(value)) + value = new Array(value); + assert_in_array(getComputedStyle(element).gridTemplateAreas, value, "gridTemplateAreas"); + } + + function testGridTemplateAreas(gridId, style, value) { + test(function() { + var grid = document.getElementById(gridId); + grid.style.gridTemplateAreas = style; + checkGridTemplateAreas(grid, value); + }, "'" + gridId + "' with: grid-template-areas: " + style + ";"); + } + + return { + testGridTemplateColumnsRows: testGridTemplateColumnsRows, + testGridTemplateAreas: testGridTemplateAreas + } +})();