1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-28 05:25:09 +00:00

LibWeb: Parse the content property

For now, we only understand `none`, `normal`, `<image>` and `<string>`.
The various other functions and identifiers can be added later.

We can *almost* use a StyleValueList for this, except it's divided into
two parts - the content, and the optional "alt text". So, I've added a
new StyleValue for it.
This commit is contained in:
Sam Atkins 2022-02-23 19:56:25 +00:00 committed by Andreas Kling
parent a9ad72cc0f
commit adaab23149
6 changed files with 120 additions and 0 deletions

View file

@ -3280,6 +3280,66 @@ RefPtr<StyleValue> Parser::parse_single_box_shadow_value(TokenStream<StyleCompon
return BoxShadowStyleValue::create(color.release_value(), offset_x.release_value(), offset_y.release_value(), blur_radius.release_value(), spread_distance.release_value(), placement.release_value());
}
RefPtr<StyleValue> Parser::parse_content_value(Vector<StyleComponentValueRule> const& component_values)
{
// FIXME: `content` accepts several kinds of function() type, which we don't handle in property_accepts_value() yet.
auto is_single_value_identifier = [](ValueID identifier) -> bool {
switch (identifier) {
case ValueID::None:
case ValueID::Normal:
return true;
default:
return false;
}
};
if (component_values.size() == 1) {
if (auto identifier = parse_identifier_value(component_values.first())) {
if (is_single_value_identifier(identifier->to_identifier()))
return identifier;
}
}
NonnullRefPtrVector<StyleValue> content_values;
NonnullRefPtrVector<StyleValue> alt_text_values;
bool in_alt_text = false;
for (auto const& value : component_values) {
if (value.is(Token::Type::Delim) && value.token().delim() == "/"sv) {
if (in_alt_text || content_values.is_empty())
return {};
in_alt_text = true;
continue;
}
auto style_value = parse_css_value(value);
if (style_value && property_accepts_value(PropertyID::Content, *style_value)) {
if (is_single_value_identifier(style_value->to_identifier()))
return {};
if (in_alt_text) {
alt_text_values.append(style_value.release_nonnull());
} else {
content_values.append(style_value.release_nonnull());
}
continue;
}
return {};
}
if (content_values.is_empty())
return {};
if (in_alt_text && alt_text_values.is_empty())
return {};
RefPtr<StyleValueList> alt_text;
if (!alt_text_values.is_empty())
alt_text = StyleValueList::create(move(alt_text_values), StyleValueList::Separator::Space);
return ContentStyleValue::create(StyleValueList::create(move(content_values), StyleValueList::Separator::Space), move(alt_text));
}
RefPtr<StyleValue> Parser::parse_flex_value(Vector<StyleComponentValueRule> const& component_values)
{
if (component_values.size() == 1) {
@ -3864,6 +3924,10 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value
if (auto parsed_value = parse_box_shadow_value(component_values))
return parsed_value.release_nonnull();
return ParsingResult::SyntaxError;
case PropertyID::Content:
if (auto parsed_value = parse_content_value(component_values))
return parsed_value.release_nonnull();
return ParsingResult::SyntaxError;
case PropertyID::Flex:
if (auto parsed_value = parse_flex_value(component_values))
return parsed_value.release_nonnull();