Skip to content

Commit adaab23

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

File tree

6 files changed

+120
-0
lines changed

6 files changed

+120
-0
lines changed

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

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3280,6 +3280,66 @@ RefPtr<StyleValue> Parser::parse_single_box_shadow_value(TokenStream<StyleCompon
32803280
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());
32813281
}
32823282

3283+
RefPtr<StyleValue> Parser::parse_content_value(Vector<StyleComponentValueRule> const& component_values)
3284+
{
3285+
// FIXME: `content` accepts several kinds of function() type, which we don't handle in property_accepts_value() yet.
3286+
3287+
auto is_single_value_identifier = [](ValueID identifier) -> bool {
3288+
switch (identifier) {
3289+
case ValueID::None:
3290+
case ValueID::Normal:
3291+
return true;
3292+
default:
3293+
return false;
3294+
}
3295+
};
3296+
3297+
if (component_values.size() == 1) {
3298+
if (auto identifier = parse_identifier_value(component_values.first())) {
3299+
if (is_single_value_identifier(identifier->to_identifier()))
3300+
return identifier;
3301+
}
3302+
}
3303+
3304+
NonnullRefPtrVector<StyleValue> content_values;
3305+
NonnullRefPtrVector<StyleValue> alt_text_values;
3306+
bool in_alt_text = false;
3307+
3308+
for (auto const& value : component_values) {
3309+
if (value.is(Token::Type::Delim) && value.token().delim() == "/"sv) {
3310+
if (in_alt_text || content_values.is_empty())
3311+
return {};
3312+
in_alt_text = true;
3313+
continue;
3314+
}
3315+
auto style_value = parse_css_value(value);
3316+
if (style_value && property_accepts_value(PropertyID::Content, *style_value)) {
3317+
if (is_single_value_identifier(style_value->to_identifier()))
3318+
return {};
3319+
3320+
if (in_alt_text) {
3321+
alt_text_values.append(style_value.release_nonnull());
3322+
} else {
3323+
content_values.append(style_value.release_nonnull());
3324+
}
3325+
continue;
3326+
}
3327+
3328+
return {};
3329+
}
3330+
3331+
if (content_values.is_empty())
3332+
return {};
3333+
if (in_alt_text && alt_text_values.is_empty())
3334+
return {};
3335+
3336+
RefPtr<StyleValueList> alt_text;
3337+
if (!alt_text_values.is_empty())
3338+
alt_text = StyleValueList::create(move(alt_text_values), StyleValueList::Separator::Space);
3339+
3340+
return ContentStyleValue::create(StyleValueList::create(move(content_values), StyleValueList::Separator::Space), move(alt_text));
3341+
}
3342+
32833343
RefPtr<StyleValue> Parser::parse_flex_value(Vector<StyleComponentValueRule> const& component_values)
32843344
{
32853345
if (component_values.size() == 1) {
@@ -3864,6 +3924,10 @@ Result<NonnullRefPtr<StyleValue>, Parser::ParsingResult> Parser::parse_css_value
38643924
if (auto parsed_value = parse_box_shadow_value(component_values))
38653925
return parsed_value.release_nonnull();
38663926
return ParsingResult::SyntaxError;
3927+
case PropertyID::Content:
3928+
if (auto parsed_value = parse_content_value(component_values))
3929+
return parsed_value.release_nonnull();
3930+
return ParsingResult::SyntaxError;
38673931
case PropertyID::Flex:
38683932
if (auto parsed_value = parse_flex_value(component_values))
38693933
return parsed_value.release_nonnull();

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,6 +274,7 @@ class Parser {
274274
RefPtr<StyleValue> parse_border_radius_shorthand_value(Vector<StyleComponentValueRule> const&);
275275
RefPtr<StyleValue> parse_box_shadow_value(Vector<StyleComponentValueRule> const&);
276276
RefPtr<StyleValue> parse_single_box_shadow_value(TokenStream<StyleComponentValueRule>&);
277+
RefPtr<StyleValue> parse_content_value(Vector<StyleComponentValueRule> const&);
277278
RefPtr<StyleValue> parse_flex_value(Vector<StyleComponentValueRule> const&);
278279
RefPtr<StyleValue> parse_flex_flow_value(Vector<StyleComponentValueRule> const&);
279280
RefPtr<StyleValue> parse_font_value(Vector<StyleComponentValueRule> const&);

Userland/Libraries/LibWeb/CSS/Properties.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,18 @@
510510
"hashless-hex-color"
511511
]
512512
},
513+
"content": {
514+
"inherited": false,
515+
"initial": "normal",
516+
"__comment": "FIXME: This accepts a whole lot of other types and identifiers!",
517+
"valid-types": [
518+
"string"
519+
],
520+
"valid-identifiers": [
521+
"normal",
522+
"none"
523+
]
524+
},
513525
"cursor": {
514526
"inherited": true,
515527
"initial": "auto",

Userland/Libraries/LibWeb/CSS/StyleValue.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ ColorStyleValue const& StyleValue::as_color() const
8181
return static_cast<ColorStyleValue const&>(*this);
8282
}
8383

84+
ContentStyleValue const& StyleValue::as_content() const
85+
{
86+
VERIFY(is_content());
87+
return static_cast<ContentStyleValue const&>(*this);
88+
}
89+
8490
FlexStyleValue const& StyleValue::as_flex() const
8591
{
8692
VERIFY(is_flex());
@@ -1015,6 +1021,13 @@ String CombinedBorderRadiusStyleValue::to_string() const
10151021
return String::formatted("{} {} {} {} / {} {} {} {}", m_top_left->horizontal_radius().to_string(), m_top_right->horizontal_radius().to_string(), m_bottom_right->horizontal_radius().to_string(), m_bottom_left->horizontal_radius().to_string(), m_top_left->vertical_radius().to_string(), m_top_right->vertical_radius().to_string(), m_bottom_right->vertical_radius().to_string(), m_bottom_left->vertical_radius().to_string());
10161022
}
10171023

1024+
String ContentStyleValue::to_string() const
1025+
{
1026+
if (has_alt_text())
1027+
return String::formatted("{} / {}", m_content->to_string(), m_alt_text->to_string());
1028+
return m_content->to_string();
1029+
}
1030+
10181031
String FlexStyleValue::to_string() const
10191032
{
10201033
return String::formatted("{} {} {}", m_grow->to_string(), m_shrink->to_string(), m_basis->to_string());

Userland/Libraries/LibWeb/CSS/StyleValue.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,7 @@ class StyleValue : public RefCounted<StyleValue> {
297297
Calculated,
298298
Color,
299299
CombinedBorderRadius,
300+
Content,
300301
Flex,
301302
FlexFlow,
302303
Font,
@@ -333,6 +334,7 @@ class StyleValue : public RefCounted<StyleValue> {
333334
bool is_box_shadow() const { return type() == Type::BoxShadow; }
334335
bool is_calculated() const { return type() == Type::Calculated; }
335336
bool is_color() const { return type() == Type::Color; }
337+
bool is_content() const { return type() == Type::Content; }
336338
bool is_flex() const { return type() == Type::Flex; }
337339
bool is_flex_flow() const { return type() == Type::FlexFlow; }
338340
bool is_font() const { return type() == Type::Font; }
@@ -367,6 +369,7 @@ class StyleValue : public RefCounted<StyleValue> {
367369
BoxShadowStyleValue const& as_box_shadow() const;
368370
CalculatedStyleValue const& as_calculated() const;
369371
ColorStyleValue const& as_color() const;
372+
ContentStyleValue const& as_content() const;
370373
FlexFlowStyleValue const& as_flex_flow() const;
371374
FlexStyleValue const& as_flex() const;
372375
FontStyleValue const& as_font() const;
@@ -399,6 +402,7 @@ class StyleValue : public RefCounted<StyleValue> {
399402
BoxShadowStyleValue& as_box_shadow() { return const_cast<BoxShadowStyleValue&>(const_cast<StyleValue const&>(*this).as_box_shadow()); }
400403
CalculatedStyleValue& as_calculated() { return const_cast<CalculatedStyleValue&>(const_cast<StyleValue const&>(*this).as_calculated()); }
401404
ColorStyleValue& as_color() { return const_cast<ColorStyleValue&>(const_cast<StyleValue const&>(*this).as_color()); }
405+
ContentStyleValue& as_content() { return const_cast<ContentStyleValue&>(const_cast<StyleValue const&>(*this).as_content()); }
402406
FlexFlowStyleValue& as_flex_flow() { return const_cast<FlexFlowStyleValue&>(const_cast<StyleValue const&>(*this).as_flex_flow()); }
403407
FlexStyleValue& as_flex() { return const_cast<FlexStyleValue&>(const_cast<StyleValue const&>(*this).as_flex()); }
404408
FontStyleValue& as_font() { return const_cast<FontStyleValue&>(const_cast<StyleValue const&>(*this).as_font()); }
@@ -969,6 +973,31 @@ class CombinedBorderRadiusStyleValue final : public StyleValue {
969973
NonnullRefPtr<BorderRadiusStyleValue> m_bottom_left;
970974
};
971975

976+
class ContentStyleValue final : public StyleValue {
977+
public:
978+
static NonnullRefPtr<ContentStyleValue> create(NonnullRefPtr<StyleValueList> content, RefPtr<StyleValueList> alt_text)
979+
{
980+
return adopt_ref(*new ContentStyleValue(move(content), move(alt_text)));
981+
}
982+
983+
StyleValueList const& content() const { return *m_content; }
984+
bool has_alt_text() const { return !m_alt_text.is_null(); }
985+
StyleValueList const* alt_text() const { return m_alt_text; }
986+
987+
virtual String to_string() const override;
988+
989+
private:
990+
ContentStyleValue(NonnullRefPtr<StyleValueList> content, RefPtr<StyleValueList> alt_text)
991+
: StyleValue(Type::Content)
992+
, m_content(move(content))
993+
, m_alt_text(move(alt_text))
994+
{
995+
}
996+
997+
NonnullRefPtr<StyleValueList> m_content;
998+
RefPtr<StyleValueList> m_alt_text;
999+
};
1000+
9721001
class FlexStyleValue final : public StyleValue {
9731002
public:
9741003
static NonnullRefPtr<FlexStyleValue> create(

Userland/Libraries/LibWeb/Forward.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ class BorderStyleValue;
3030
class BoxShadowStyleValue;
3131
class CalculatedStyleValue;
3232
class ColorStyleValue;
33+
class ContentStyleValue;
3334
class CSSImportRule;
3435
class CSSMediaRule;
3536
class CSSRule;

0 commit comments

Comments
 (0)