Skip to content

Commit b51f428

Browse files
AtkinsSJawesomekling
authored andcommitted
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.
1 parent e5b0369 commit b51f428

File tree

3 files changed

+46
-21
lines changed

3 files changed

+46
-21
lines changed

Base/res/html/misc/box-shadow.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,5 +37,9 @@ <h1>Box-shadow Tests</h1>
3737
<p>box-shadow: 20px 10px 5px magenta</p>
3838
</div>
3939

40+
<div class="box" style="box-shadow: 20px 10px 5px magenta, cyan -20px -10px 5px, yellow 10px -5px 5px 20px">
41+
<p>box-shadow: 20px 10px 5px magenta, cyan -20px -10px 5px, yellow 10px -5px 5px 20px</p>
42+
</div>
43+
4044
</body>
4145
</html>

Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp

Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3169,66 +3169,86 @@ RefPtr<StyleValue> Parser::parse_box_shadow_value(Vector<StyleComponentValueRule
31693169
return ident;
31703170
}
31713171

3172-
// FIXME: Also support multiple comma-separated box-shadows
3172+
return parse_comma_separated_value_list(component_values, [this](auto& tokens) {
3173+
return parse_single_box_shadow_value(tokens);
3174+
});
3175+
}
3176+
3177+
RefPtr<StyleValue> Parser::parse_single_box_shadow_value(TokenStream<StyleComponentValueRule>& tokens)
3178+
{
3179+
auto start_position = tokens.position();
3180+
auto error = [&]() {
3181+
tokens.rewind_to_position(start_position);
3182+
return nullptr;
3183+
};
3184+
31733185
Optional<Color> color;
31743186
Optional<Length> offset_x;
31753187
Optional<Length> offset_y;
31763188
Optional<Length> blur_radius;
31773189
Optional<Length> spread_distance;
31783190
Optional<BoxShadowPlacement> placement;
31793191

3180-
for (size_t i = 0; i < component_values.size(); ++i) {
3181-
if (auto maybe_color = parse_color(component_values[i]); maybe_color.has_value()) {
3192+
while (tokens.has_next_token()) {
3193+
auto& token = tokens.peek_token();
3194+
3195+
if (auto maybe_color = parse_color(token); maybe_color.has_value()) {
31823196
if (color.has_value())
3183-
return nullptr;
3197+
return error();
31843198
color = maybe_color.release_value();
3199+
tokens.next_token();
31853200
continue;
31863201
}
31873202

3188-
if (auto maybe_offset_x = parse_length(component_values[i]); maybe_offset_x.has_value()) {
3203+
if (auto maybe_offset_x = parse_length(token); maybe_offset_x.has_value()) {
31893204
// horizontal offset
31903205
if (offset_x.has_value())
3191-
return nullptr;
3206+
return error();
31923207
offset_x = maybe_offset_x.release_value();
3208+
tokens.next_token();
31933209

31943210
// vertical offset
3195-
if (++i >= component_values.size())
3196-
return nullptr;
3197-
auto maybe_offset_y = parse_length(component_values[i]);
3211+
if (!tokens.has_next_token())
3212+
return error();
3213+
auto maybe_offset_y = parse_length(tokens.peek_token());
31983214
if (!maybe_offset_y.has_value())
3199-
return nullptr;
3215+
return error();
32003216
offset_y = maybe_offset_y.release_value();
3217+
tokens.next_token();
32013218

32023219
// blur radius (optional)
3203-
if (i + 1 >= component_values.size())
3220+
if (!tokens.has_next_token())
32043221
break;
3205-
auto maybe_blur_radius = parse_length(component_values[i + 1]);
3222+
auto maybe_blur_radius = parse_length(tokens.peek_token());
32063223
if (!maybe_blur_radius.has_value())
32073224
continue;
3208-
++i;
32093225
blur_radius = maybe_blur_radius.release_value();
3226+
tokens.next_token();
32103227

32113228
// spread distance (optional)
3212-
if (i + 1 >= component_values.size())
3229+
if (!tokens.has_next_token())
32133230
break;
3214-
auto maybe_spread_distance = parse_length(component_values[i + 1]);
3231+
auto maybe_spread_distance = parse_length(tokens.peek_token());
32153232
if (!maybe_spread_distance.has_value())
32163233
continue;
3217-
++i;
32183234
spread_distance = maybe_spread_distance.release_value();
3235+
tokens.next_token();
32193236

32203237
continue;
32213238
}
32223239

3223-
if (component_values[i].is(Token::Type::Ident) && component_values[i].token().ident().equals_ignoring_case("inset"sv)) {
3240+
if (token.is(Token::Type::Ident) && token.token().ident().equals_ignoring_case("inset"sv)) {
32243241
if (placement.has_value())
3225-
return nullptr;
3242+
return error();
32263243
placement = BoxShadowPlacement::Inner;
3244+
tokens.next_token();
32273245
continue;
32283246
}
32293247

3230-
// Unrecognized value
3231-
return nullptr;
3248+
if (token.is(Token::Type::Comma))
3249+
break;
3250+
3251+
return error();
32323252
}
32333253

32343254
// FIXME: If color is absent, default to `currentColor`
@@ -3237,7 +3257,7 @@ RefPtr<StyleValue> Parser::parse_box_shadow_value(Vector<StyleComponentValueRule
32373257

32383258
// x/y offsets are required
32393259
if (!offset_x.has_value() || !offset_y.has_value())
3240-
return nullptr;
3260+
return error();
32413261

32423262
// Other lengths default to 0
32433263
if (!blur_radius.has_value())

Userland/Libraries/LibWeb/CSS/Parser/Parser.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ class Parser {
232232
RefPtr<StyleValue> parse_border_radius_value(Vector<StyleComponentValueRule> const&);
233233
RefPtr<StyleValue> parse_border_radius_shorthand_value(Vector<StyleComponentValueRule> const&);
234234
RefPtr<StyleValue> parse_box_shadow_value(Vector<StyleComponentValueRule> const&);
235+
RefPtr<StyleValue> parse_single_box_shadow_value(TokenStream<StyleComponentValueRule>&);
235236
RefPtr<StyleValue> parse_flex_value(Vector<StyleComponentValueRule> const&);
236237
RefPtr<StyleValue> parse_flex_flow_value(Vector<StyleComponentValueRule> const&);
237238
RefPtr<StyleValue> parse_font_value(Vector<StyleComponentValueRule> const&);

0 commit comments

Comments
 (0)