|
@@ -3169,7 +3169,19 @@ RefPtr<StyleValue> Parser::parse_box_shadow_value(Vector<StyleComponentValueRule
|
|
return ident;
|
|
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<Color> color;
|
|
Optional<Length> offset_x;
|
|
Optional<Length> offset_x;
|
|
Optional<Length> offset_y;
|
|
Optional<Length> offset_y;
|
|
@@ -3177,58 +3189,66 @@ RefPtr<StyleValue> Parser::parse_box_shadow_value(Vector<StyleComponentValueRule
|
|
Optional<Length> spread_distance;
|
|
Optional<Length> spread_distance;
|
|
Optional<BoxShadowPlacement> placement;
|
|
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())
|
|
if (color.has_value())
|
|
- return nullptr;
|
|
|
|
|
|
+ return error();
|
|
color = maybe_color.release_value();
|
|
color = maybe_color.release_value();
|
|
|
|
+ tokens.next_token();
|
|
continue;
|
|
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
|
|
// horizontal offset
|
|
if (offset_x.has_value())
|
|
if (offset_x.has_value())
|
|
- return nullptr;
|
|
|
|
|
|
+ return error();
|
|
offset_x = maybe_offset_x.release_value();
|
|
offset_x = maybe_offset_x.release_value();
|
|
|
|
+ tokens.next_token();
|
|
|
|
|
|
// vertical offset
|
|
// 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())
|
|
if (!maybe_offset_y.has_value())
|
|
- return nullptr;
|
|
|
|
|
|
+ return error();
|
|
offset_y = maybe_offset_y.release_value();
|
|
offset_y = maybe_offset_y.release_value();
|
|
|
|
+ tokens.next_token();
|
|
|
|
|
|
// blur radius (optional)
|
|
// blur radius (optional)
|
|
- if (i + 1 >= component_values.size())
|
|
|
|
|
|
+ if (!tokens.has_next_token())
|
|
break;
|
|
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())
|
|
if (!maybe_blur_radius.has_value())
|
|
continue;
|
|
continue;
|
|
- ++i;
|
|
|
|
blur_radius = maybe_blur_radius.release_value();
|
|
blur_radius = maybe_blur_radius.release_value();
|
|
|
|
+ tokens.next_token();
|
|
|
|
|
|
// spread distance (optional)
|
|
// spread distance (optional)
|
|
- if (i + 1 >= component_values.size())
|
|
|
|
|
|
+ if (!tokens.has_next_token())
|
|
break;
|
|
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())
|
|
if (!maybe_spread_distance.has_value())
|
|
continue;
|
|
continue;
|
|
- ++i;
|
|
|
|
spread_distance = maybe_spread_distance.release_value();
|
|
spread_distance = maybe_spread_distance.release_value();
|
|
|
|
+ tokens.next_token();
|
|
|
|
|
|
continue;
|
|
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())
|
|
if (placement.has_value())
|
|
- return nullptr;
|
|
|
|
|
|
+ return error();
|
|
placement = BoxShadowPlacement::Inner;
|
|
placement = BoxShadowPlacement::Inner;
|
|
|
|
+ tokens.next_token();
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
|
|
|
|
- // Unrecognized value
|
|
|
|
- return nullptr;
|
|
|
|
|
|
+ if (token.is(Token::Type::Comma))
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ return error();
|
|
}
|
|
}
|
|
|
|
|
|
// FIXME: If color is absent, default to `currentColor`
|
|
// 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
|
|
// x/y offsets are required
|
|
if (!offset_x.has_value() || !offset_y.has_value())
|
|
if (!offset_x.has_value() || !offset_y.has_value())
|
|
- return nullptr;
|
|
|
|
|
|
+ return error();
|
|
|
|
|
|
// Other lengths default to 0
|
|
// Other lengths default to 0
|
|
if (!blur_radius.has_value())
|
|
if (!blur_radius.has_value())
|