From 8fd4678e7943239f6f49cb41e7179a6ba199574f Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Mon, 8 Nov 2021 17:19:55 +0000 Subject: LibWeb: Parse comma-separated lists for most background properties We now can parse lists of values for these properties: - `background-attachment` - `background-clip` - `background-image` - `background-origin` - `background-position` - `background-repeat` - `background-size` This uses two new Parser methods: `parse_simple_comma_separated_value_list()` for the simple case when each value is parsed from a single token; and `parse_comma_separated_value_list()` which takes a lambda for when parsing each value is more involved. This also means that any unconsumed tokens at the end will make the parsing fail as it should, where previously we just ignored them. --- Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 85 +++++++++++++------------ Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 8 +-- 2 files changed, 47 insertions(+), 46 deletions(-) (limited to 'Userland/Libraries/LibWeb') diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 9f4e511708..77b77e5eba 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -2345,6 +2345,42 @@ RefPtr Parser::parse_image_value(StyleComponentValueRule const& comp return {}; } +template +RefPtr Parser::parse_comma_separated_value_list(Vector const& component_values, ParseFunction parse_one_value) +{ + auto tokens = TokenStream { component_values }; + auto first = parse_one_value(tokens); + if (!first || !tokens.has_next_token()) + return first; + + NonnullRefPtrVector values; + values.append(first.release_nonnull()); + + while (tokens.has_next_token()) { + if (!tokens.next_token().is(Token::Type::Comma)) + return {}; + + if (auto maybe_value = parse_one_value(tokens)) { + values.append(maybe_value.release_nonnull()); + continue; + } + return {}; + } + + return StyleValueList::create(move(values)); +} + +RefPtr Parser::parse_simple_comma_separated_value_list(Vector const& component_values) +{ + return parse_comma_separated_value_list(component_values, [=, this](auto& tokens) -> RefPtr { + auto& token = tokens.next_token(); + if (auto value = parse_css_value(token); value && property_accepts_value(m_context.current_property_id(), *value)) + return value; + tokens.reconsume_current_input_token(); + return nullptr; + }); +} + RefPtr Parser::parse_background_value(Vector const& component_values) { RefPtr background_color; @@ -2473,23 +2509,6 @@ RefPtr Parser::parse_background_value(Vector Parser::parse_background_image_value(Vector const& component_values) -{ - if (component_values.size() == 1) { - auto maybe_value = parse_css_value(component_values.first()); - if (!maybe_value) - return nullptr; - auto value = maybe_value.release_nonnull(); - if (property_accepts_value(PropertyID::BackgroundImage, *value)) - return value; - return nullptr; - } - - // FIXME: Handle multiple sets of comma-separated values. - dbgln("CSS Parser does not yet support multiple comma-separated values for background-image."); - return nullptr; -} - RefPtr Parser::parse_single_background_position_value(TokenStream& tokens) { // NOTE: This *looks* like it parses a , but it doesn't. From the spec: @@ -2652,13 +2671,6 @@ RefPtr Parser::parse_single_background_position_value(TokenStreamedge, vertical->offset); } -RefPtr Parser::parse_background_position_value(Vector const& component_values) -{ - auto tokens = TokenStream { component_values }; - // FIXME: Handle multiple sets of comma-separated values. - return parse_single_background_position_value(tokens); -} - RefPtr Parser::parse_single_background_repeat_value(TokenStream& tokens) { auto start_position = tokens.position(); @@ -2714,13 +2726,6 @@ RefPtr Parser::parse_single_background_repeat_value(TokenStreamto_identifier()), as_repeat(y_value->to_identifier())); } -RefPtr Parser::parse_background_repeat_value(Vector const& component_values) -{ - auto tokens = TokenStream { component_values }; - // FIXME: Handle multiple sets of comma-separated values. - return parse_single_background_repeat_value(tokens); -} - RefPtr Parser::parse_single_background_size_value(TokenStream& tokens) { auto start_position = tokens.position(); @@ -2749,13 +2754,6 @@ RefPtr Parser::parse_single_background_size_value(TokenStream Parser::parse_background_size_value(Vector const& component_values) -{ - auto tokens = TokenStream { component_values }; - // FIXME: Handle multiple sets of comma-separated values. - return parse_single_background_size_value(tokens); -} - RefPtr Parser::parse_border_value(Vector const& component_values) { if (component_values.size() > 3) @@ -3472,20 +3470,23 @@ Result, Parser::ParsingResult> Parser::parse_css_value if (auto parsed_value = parse_background_value(component_values)) return parsed_value.release_nonnull(); return ParsingResult::SyntaxError; + case PropertyID::BackgroundAttachment: + case PropertyID::BackgroundClip: case PropertyID::BackgroundImage: - if (auto parsed_value = parse_background_image_value(component_values)) + case PropertyID::BackgroundOrigin: + if (auto parsed_value = parse_simple_comma_separated_value_list(component_values)) return parsed_value.release_nonnull(); return ParsingResult::SyntaxError; case PropertyID::BackgroundPosition: - if (auto parsed_value = parse_background_position_value(component_values)) + if (auto parsed_value = parse_comma_separated_value_list(component_values, [this](auto& tokens) { return parse_single_background_position_value(tokens); })) return parsed_value.release_nonnull(); return ParsingResult::SyntaxError; case PropertyID::BackgroundRepeat: - if (auto parsed_value = parse_background_repeat_value(component_values)) + if (auto parsed_value = parse_comma_separated_value_list(component_values, [this](auto& tokens) { return parse_single_background_repeat_value(tokens); })) return parsed_value.release_nonnull(); return ParsingResult::SyntaxError; case PropertyID::BackgroundSize: - if (auto parsed_value = parse_background_size_value(component_values)) + if (auto parsed_value = parse_comma_separated_value_list(component_values, [this](auto& tokens) { return parse_single_background_size_value(tokens); })) return parsed_value.release_nonnull(); return ParsingResult::SyntaxError; case PropertyID::Border: diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 1d2225f601..578b2e56ac 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -198,14 +198,14 @@ private: RefPtr parse_color_value(StyleComponentValueRule const&); RefPtr parse_string_value(StyleComponentValueRule const&); RefPtr parse_image_value(StyleComponentValueRule const&); + template + RefPtr parse_comma_separated_value_list(Vector const&, ParseFunction); + RefPtr parse_simple_comma_separated_value_list(Vector const&); + RefPtr parse_background_value(Vector const&); - RefPtr parse_background_image_value(Vector const&); RefPtr parse_single_background_position_value(TokenStream&); - RefPtr parse_background_position_value(Vector const&); RefPtr parse_single_background_repeat_value(TokenStream&); - RefPtr parse_background_repeat_value(Vector const&); RefPtr parse_single_background_size_value(TokenStream&); - RefPtr parse_background_size_value(Vector const&); RefPtr parse_border_value(Vector const&); RefPtr parse_border_radius_value(Vector const&); RefPtr parse_border_radius_shorthand_value(Vector const&); -- cgit v1.2.3