diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2021-11-08 17:19:55 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-11-17 22:20:01 +0100 |
commit | 8fd4678e7943239f6f49cb41e7179a6ba199574f (patch) | |
tree | 31c2466d607a6cc56d69edb817f9d901587a41c8 | |
parent | 50b15bdc1d175f4706b0dc57413202fb300629cc (diff) | |
download | serenity-8fd4678e7943239f6f49cb41e7179a6ba199574f.zip |
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.
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 85 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 8 |
2 files changed, 47 insertions, 46 deletions
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<StyleValue> Parser::parse_image_value(StyleComponentValueRule const& comp return {}; } +template<typename ParseFunction> +RefPtr<StyleValue> Parser::parse_comma_separated_value_list(Vector<StyleComponentValueRule> 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<StyleValue> 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<StyleValue> Parser::parse_simple_comma_separated_value_list(Vector<StyleComponentValueRule> const& component_values) +{ + return parse_comma_separated_value_list(component_values, [=, this](auto& tokens) -> RefPtr<StyleValue> { + 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<StyleValue> Parser::parse_background_value(Vector<StyleComponentValueRule> const& component_values) { RefPtr<StyleValue> background_color; @@ -2473,23 +2509,6 @@ RefPtr<StyleValue> Parser::parse_background_value(Vector<StyleComponentValueRule background_clip.release_nonnull()); } -RefPtr<StyleValue> Parser::parse_background_image_value(Vector<StyleComponentValueRule> 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<StyleValue> Parser::parse_single_background_position_value(TokenStream<StyleComponentValueRule>& tokens) { // NOTE: This *looks* like it parses a <position>, but it doesn't. From the spec: @@ -2652,13 +2671,6 @@ RefPtr<StyleValue> Parser::parse_single_background_position_value(TokenStream<St vertical->edge, vertical->offset); } -RefPtr<StyleValue> Parser::parse_background_position_value(Vector<StyleComponentValueRule> const& component_values) -{ - auto tokens = TokenStream { component_values }; - // FIXME: Handle multiple sets of comma-separated values. - return parse_single_background_position_value(tokens); -} - RefPtr<StyleValue> Parser::parse_single_background_repeat_value(TokenStream<StyleComponentValueRule>& tokens) { auto start_position = tokens.position(); @@ -2714,13 +2726,6 @@ RefPtr<StyleValue> Parser::parse_single_background_repeat_value(TokenStream<Styl return BackgroundRepeatStyleValue::create(as_repeat(x_value->to_identifier()), as_repeat(y_value->to_identifier())); } -RefPtr<StyleValue> Parser::parse_background_repeat_value(Vector<StyleComponentValueRule> const& component_values) -{ - auto tokens = TokenStream { component_values }; - // FIXME: Handle multiple sets of comma-separated values. - return parse_single_background_repeat_value(tokens); -} - RefPtr<StyleValue> Parser::parse_single_background_size_value(TokenStream<StyleComponentValueRule>& tokens) { auto start_position = tokens.position(); @@ -2749,13 +2754,6 @@ RefPtr<StyleValue> Parser::parse_single_background_size_value(TokenStream<StyleC return error(); } -RefPtr<StyleValue> Parser::parse_background_size_value(Vector<StyleComponentValueRule> const& component_values) -{ - auto tokens = TokenStream { component_values }; - // FIXME: Handle multiple sets of comma-separated values. - return parse_single_background_size_value(tokens); -} - RefPtr<StyleValue> Parser::parse_border_value(Vector<StyleComponentValueRule> const& component_values) { if (component_values.size() > 3) @@ -3472,20 +3470,23 @@ Result<NonnullRefPtr<StyleValue>, 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<StyleValue> parse_color_value(StyleComponentValueRule const&); RefPtr<StyleValue> parse_string_value(StyleComponentValueRule const&); RefPtr<StyleValue> parse_image_value(StyleComponentValueRule const&); + template<typename ParseFunction> + RefPtr<StyleValue> parse_comma_separated_value_list(Vector<StyleComponentValueRule> const&, ParseFunction); + RefPtr<StyleValue> parse_simple_comma_separated_value_list(Vector<StyleComponentValueRule> const&); + RefPtr<StyleValue> parse_background_value(Vector<StyleComponentValueRule> const&); - RefPtr<StyleValue> parse_background_image_value(Vector<StyleComponentValueRule> const&); RefPtr<StyleValue> parse_single_background_position_value(TokenStream<StyleComponentValueRule>&); - RefPtr<StyleValue> parse_background_position_value(Vector<StyleComponentValueRule> const&); RefPtr<StyleValue> parse_single_background_repeat_value(TokenStream<StyleComponentValueRule>&); - RefPtr<StyleValue> parse_background_repeat_value(Vector<StyleComponentValueRule> const&); RefPtr<StyleValue> parse_single_background_size_value(TokenStream<StyleComponentValueRule>&); - RefPtr<StyleValue> parse_background_size_value(Vector<StyleComponentValueRule> const&); RefPtr<StyleValue> parse_border_value(Vector<StyleComponentValueRule> const&); RefPtr<StyleValue> parse_border_radius_value(Vector<StyleComponentValueRule> const&); RefPtr<StyleValue> parse_border_radius_shorthand_value(Vector<StyleComponentValueRule> const&); |