diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 2a99cafe5a6..ddd9960e4f9 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -2310,33 +2310,43 @@ Vector Parser::parse_unicode_ranges(TokenStream Parser::parse_dimension_value(TokenStream& tokens) { - auto dimension = parse_dimension(tokens.peek_token()); - if (!dimension.has_value()) - return nullptr; - (void)tokens.next_token(); // dimension + if (auto dimension = parse_dimension(tokens.peek_token()); dimension.has_value()) { + (void)tokens.next_token(); // dimension - if (dimension->is_angle()) - return AngleStyleValue::create(dimension->angle()); - if (dimension->is_frequency()) - return FrequencyStyleValue::create(dimension->frequency()); - if (dimension->is_length()) - return LengthStyleValue::create(dimension->length()); - if (dimension->is_percentage()) - return PercentageStyleValue::create(dimension->percentage()); - if (dimension->is_resolution()) - return ResolutionStyleValue::create(dimension->resolution()); - if (dimension->is_time()) - return TimeStyleValue::create(dimension->time()); - VERIFY_NOT_REACHED(); + if (dimension->is_angle()) + return AngleStyleValue::create(dimension->angle()); + if (dimension->is_frequency()) + return FrequencyStyleValue::create(dimension->frequency()); + if (dimension->is_length()) + return LengthStyleValue::create(dimension->length()); + if (dimension->is_percentage()) + return PercentageStyleValue::create(dimension->percentage()); + if (dimension->is_resolution()) + return ResolutionStyleValue::create(dimension->resolution()); + if (dimension->is_time()) + return TimeStyleValue::create(dimension->time()); + VERIFY_NOT_REACHED(); + } + + if (auto calc = parse_calculated_value(tokens.peek_token()); calc && calc->resolves_to_dimension()) { + (void)tokens.next_token(); // calc + return calc; + } + + return nullptr; } RefPtr Parser::parse_integer_value(TokenStream& tokens) { auto peek_token = tokens.peek_token(); if (peek_token.is(Token::Type::Number) && peek_token.token().number().is_integer()) { - (void)tokens.next_token(); + (void)tokens.next_token(); // integer return IntegerStyleValue::create(peek_token.token().number().integer_value()); } + if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_number()) { + (void)tokens.next_token(); // calc + return calc; + } return nullptr; } @@ -2345,28 +2355,181 @@ RefPtr Parser::parse_number_value(TokenStream& to { auto peek_token = tokens.peek_token(); if (peek_token.is(Token::Type::Number)) { - (void)tokens.next_token(); + (void)tokens.next_token(); // number return NumberStyleValue::create(peek_token.token().number().value()); } + if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_number()) { + (void)tokens.next_token(); // calc + return calc; + } return nullptr; } -RefPtr Parser::parse_number_or_percentage_value(TokenStream& tokens) +RefPtr Parser::parse_number_percentage_value(TokenStream& tokens) { auto peek_token = tokens.peek_token(); if (peek_token.is(Token::Type::Number)) { - (void)tokens.next_token(); + (void)tokens.next_token(); // number return NumberStyleValue::create(peek_token.token().number().value()); } if (peek_token.is(Token::Type::Percentage)) { - (void)tokens.next_token(); + (void)tokens.next_token(); // percentage return PercentageStyleValue::create(Percentage(peek_token.token().percentage())); } + if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_number_percentage()) { + (void)tokens.next_token(); // calc + return calc; + } return nullptr; } +RefPtr Parser::parse_percentage_value(TokenStream& tokens) +{ + auto peek_token = tokens.peek_token(); + if (peek_token.is(Token::Type::Percentage)) { + (void)tokens.next_token(); // percentage + return PercentageStyleValue::create(Percentage(peek_token.token().percentage())); + } + if (auto calc = parse_calculated_value(peek_token); calc && calc->resolves_to_percentage()) { + (void)tokens.next_token(); // calc + return calc; + } + + return nullptr; +} + +RefPtr Parser::parse_angle_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_angle() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_angle())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_angle_percentage_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_angle() || dimension_value->is_percentage() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_angle_percentage())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_flex_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_flex() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_flex())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_frequency_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_frequency() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_frequency())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_frequency_percentage_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_frequency() || dimension_value->is_percentage() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_frequency_percentage())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_length_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_length() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_length())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_length_percentage_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_length() || dimension_value->is_percentage() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_length_percentage())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_resolution_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_resolution() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_resolution())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_time_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_time() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_time())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + +RefPtr Parser::parse_time_percentage_value(TokenStream& tokens) +{ + auto transaction = tokens.begin_transaction(); + if (auto dimension_value = parse_dimension_value(tokens)) { + if (dimension_value->is_time() || dimension_value->is_percentage() + || (dimension_value->is_calculated() && dimension_value->as_calculated().resolves_to_time_percentage())) { + transaction.commit(); + return dimension_value; + } + } + return nullptr; +} + RefPtr Parser::parse_keyword_value(TokenStream& tokens) { auto peek_token = tokens.peek_token(); @@ -4782,7 +4945,7 @@ RefPtr Parser::parse_filter_value_list_value(TokenStream Parser::parse_flex_value(TokenStream& tokens) +RefPtr Parser::parse_flex_shorthand_value(TokenStream& tokens) { auto transaction = tokens.begin_transaction(); @@ -5964,7 +6127,7 @@ RefPtr Parser::parse_transform_value(TokenStream& } else { // FIXME: Remove this reconsume once all parsing functions are TokenStream-based. argument_tokens.reconsume_current_input_token(); - auto number_or_percentage = parse_number_or_percentage_value(argument_tokens); + auto number_or_percentage = parse_number_percentage_value(argument_tokens); if (!number_or_percentage) return nullptr; values.append(number_or_percentage.release_nonnull()); @@ -7077,7 +7240,7 @@ Parser::ParseErrorOr> Parser::parse_css_value(Prope return ParseError::SyntaxError; case PropertyID::Flex: case PropertyID::WebkitFlex: - if (auto parsed_value = parse_flex_value(tokens); parsed_value && !tokens.has_next_token()) + if (auto parsed_value = parse_flex_shorthand_value(tokens); parsed_value && !tokens.has_next_token()) return parsed_value.release_nonnull(); return ParseError::SyntaxError; case PropertyID::FlexFlow: diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 43492dccf03..52fa1dcb197 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -238,10 +238,6 @@ private: // NOTE: Implemented in generated code. (GenerateCSSMathFunctions.cpp) OwnPtr parse_math_function(PropertyID, Function const&); OwnPtr parse_a_calc_function_node(Function const&); - RefPtr parse_dimension_value(TokenStream&); - RefPtr parse_integer_value(TokenStream&); - RefPtr parse_number_value(TokenStream&); - RefPtr parse_number_or_percentage_value(TokenStream&); RefPtr parse_keyword_value(TokenStream&); RefPtr parse_color_value(TokenStream&); RefPtr parse_counter_value(TokenStream&); @@ -262,6 +258,22 @@ private: RefPtr parse_position_value(TokenStream&, PositionParsingMode = PositionParsingMode::Normal); RefPtr parse_filter_value_list_value(TokenStream&); + RefPtr parse_dimension_value(TokenStream&); + RefPtr parse_angle_value(TokenStream&); + RefPtr parse_angle_percentage_value(TokenStream&); + RefPtr parse_flex_value(TokenStream&); + RefPtr parse_frequency_value(TokenStream&); + RefPtr parse_frequency_percentage_value(TokenStream&); + RefPtr parse_integer_value(TokenStream&); + RefPtr parse_length_value(TokenStream&); + RefPtr parse_length_percentage_value(TokenStream&); + RefPtr parse_number_value(TokenStream&); + RefPtr parse_number_percentage_value(TokenStream& tokens); + RefPtr parse_percentage_value(TokenStream& tokens); + RefPtr parse_resolution_value(TokenStream&); + RefPtr parse_time_value(TokenStream&); + RefPtr parse_time_percentage_value(TokenStream&); + template RefPtr parse_comma_separated_value_list(TokenStream&, ParseFunction); RefPtr parse_simple_comma_separated_value_list(PropertyID, TokenStream&); @@ -280,7 +292,7 @@ private: RefPtr parse_counter_reset_value(TokenStream&); RefPtr parse_counter_set_value(TokenStream&); RefPtr parse_display_value(TokenStream&); - RefPtr parse_flex_value(TokenStream&); + RefPtr parse_flex_shorthand_value(TokenStream&); RefPtr parse_flex_flow_value(TokenStream&); RefPtr parse_font_value(TokenStream&); RefPtr parse_font_family_value(TokenStream&); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h index eeb1905942c..3e578a73b20 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h @@ -117,6 +117,8 @@ public: Optional resolve_number() const; Optional resolve_integer() const; + bool resolves_to_dimension() const { return m_resolved_type.matches_dimension(); } + bool contains_percentage() const; private: