summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2021-11-08 17:19:55 +0000
committerAndreas Kling <kling@serenityos.org>2021-11-17 22:20:01 +0100
commit8fd4678e7943239f6f49cb41e7179a6ba199574f (patch)
tree31c2466d607a6cc56d69edb817f9d901587a41c8
parent50b15bdc1d175f4706b0dc57413202fb300629cc (diff)
downloadserenity-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.cpp85
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.h8
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&);