diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2022-02-08 14:07:06 +0000 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2022-02-08 17:45:51 +0100 |
commit | b51f428165c60120fcf30f8b5e6c785ca1aec16d (patch) | |
tree | b8814cb304afd23df966841eb9a004df782c924a | |
parent | e5b0369dfd360eb925f956cca369e115f198d895 (diff) | |
download | serenity-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.html | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 62 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 1 |
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&); |