summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2022-02-08 14:07:06 +0000
committerAndreas Kling <kling@serenityos.org>2022-02-08 17:45:51 +0100
commitb51f428165c60120fcf30f8b5e6c785ca1aec16d (patch)
treeb8814cb304afd23df966841eb9a004df782c924a
parente5b0369dfd360eb925f956cca369e115f198d895 (diff)
downloadserenity-b51f428165c60120fcf30f8b5e6c785ca1aec16d.zip
LibWeb: Parse multiple box-shadows :^)
Again, we don't yet render these (we render nothing) but this gets rid of a decent amount of CSS spam on Discord.
-rw-r--r--Base/res/html/misc/box-shadow.html4
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp62
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.h1
3 files changed, 46 insertions, 21 deletions
diff --git a/Base/res/html/misc/box-shadow.html b/Base/res/html/misc/box-shadow.html
index 5d550f0352..d469ce3bcb 100644
--- a/Base/res/html/misc/box-shadow.html
+++ b/Base/res/html/misc/box-shadow.html
@@ -37,5 +37,9 @@
<p>box-shadow: 20px 10px 5px magenta</p>
</div>
+<div class="box" style="box-shadow: 20px 10px 5px magenta, cyan -20px -10px 5px, yellow 10px -5px 5px 20px">
+ <p>box-shadow: 20px 10px 5px magenta, cyan -20px -10px 5px, yellow 10px -5px 5px 20px</p>
+</div>
+
</body>
</html>
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
index 1b7060503c..3082cd735c 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
@@ -3169,7 +3169,19 @@ RefPtr<StyleValue> Parser::parse_box_shadow_value(Vector<StyleComponentValueRule
return ident;
}
- // FIXME: Also support multiple comma-separated box-shadows
+ return parse_comma_separated_value_list(component_values, [this](auto& tokens) {
+ return parse_single_box_shadow_value(tokens);
+ });
+}
+
+RefPtr<StyleValue> Parser::parse_single_box_shadow_value(TokenStream<StyleComponentValueRule>& tokens)
+{
+ auto start_position = tokens.position();
+ auto error = [&]() {
+ tokens.rewind_to_position(start_position);
+ return nullptr;
+ };
+
Optional<Color> color;
Optional<Length> offset_x;
Optional<Length> offset_y;
@@ -3177,58 +3189,66 @@ RefPtr<StyleValue> Parser::parse_box_shadow_value(Vector<StyleComponentValueRule
Optional<Length> spread_distance;
Optional<BoxShadowPlacement> placement;
- for (size_t i = 0; i < component_values.size(); ++i) {
- if (auto maybe_color = parse_color(component_values[i]); maybe_color.has_value()) {
+ while (tokens.has_next_token()) {
+ auto& token = tokens.peek_token();
+
+ if (auto maybe_color = parse_color(token); maybe_color.has_value()) {
if (color.has_value())
- return nullptr;
+ return error();
color = maybe_color.release_value();
+ tokens.next_token();
continue;
}
- if (auto maybe_offset_x = parse_length(component_values[i]); maybe_offset_x.has_value()) {
+ if (auto maybe_offset_x = parse_length(token); maybe_offset_x.has_value()) {
// horizontal offset
if (offset_x.has_value())
- return nullptr;
+ return error();
offset_x = maybe_offset_x.release_value();
+ tokens.next_token();
// vertical offset
- if (++i >= component_values.size())
- return nullptr;
- auto maybe_offset_y = parse_length(component_values[i]);
+ if (!tokens.has_next_token())
+ return error();
+ auto maybe_offset_y = parse_length(tokens.peek_token());
if (!maybe_offset_y.has_value())
- return nullptr;
+ return error();
offset_y = maybe_offset_y.release_value();
+ tokens.next_token();
// blur radius (optional)
- if (i + 1 >= component_values.size())
+ if (!tokens.has_next_token())
break;
- auto maybe_blur_radius = parse_length(component_values[i + 1]);
+ auto maybe_blur_radius = parse_length(tokens.peek_token());
if (!maybe_blur_radius.has_value())
continue;
- ++i;
blur_radius = maybe_blur_radius.release_value();
+ tokens.next_token();
// spread distance (optional)
- if (i + 1 >= component_values.size())
+ if (!tokens.has_next_token())
break;
- auto maybe_spread_distance = parse_length(component_values[i + 1]);
+ auto maybe_spread_distance = parse_length(tokens.peek_token());
if (!maybe_spread_distance.has_value())
continue;
- ++i;
spread_distance = maybe_spread_distance.release_value();
+ tokens.next_token();
continue;
}
- if (component_values[i].is(Token::Type::Ident) && component_values[i].token().ident().equals_ignoring_case("inset"sv)) {
+ if (token.is(Token::Type::Ident) && token.token().ident().equals_ignoring_case("inset"sv)) {
if (placement.has_value())
- return nullptr;
+ return error();
placement = BoxShadowPlacement::Inner;
+ tokens.next_token();
continue;
}
- // Unrecognized value
- return nullptr;
+ if (token.is(Token::Type::Comma))
+ break;
+
+ return error();
}
// FIXME: If color is absent, default to `currentColor`
@@ -3237,7 +3257,7 @@ RefPtr<StyleValue> Parser::parse_box_shadow_value(Vector<StyleComponentValueRule
// x/y offsets are required
if (!offset_x.has_value() || !offset_y.has_value())
- return nullptr;
+ return error();
// Other lengths default to 0
if (!blur_radius.has_value())
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
index 0149c7df82..6a9e073c53 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
@@ -232,6 +232,7 @@ private:
RefPtr<StyleValue> parse_border_radius_value(Vector<StyleComponentValueRule> const&);
RefPtr<StyleValue> parse_border_radius_shorthand_value(Vector<StyleComponentValueRule> const&);
RefPtr<StyleValue> parse_box_shadow_value(Vector<StyleComponentValueRule> const&);
+ RefPtr<StyleValue> parse_single_box_shadow_value(TokenStream<StyleComponentValueRule>&);
RefPtr<StyleValue> parse_flex_value(Vector<StyleComponentValueRule> const&);
RefPtr<StyleValue> parse_flex_flow_value(Vector<StyleComponentValueRule> const&);
RefPtr<StyleValue> parse_font_value(Vector<StyleComponentValueRule> const&);