summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp64
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.h1
-rw-r--r--Userland/Libraries/LibWeb/CSS/Properties.json12
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleValue.cpp13
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleValue.h29
-rw-r--r--Userland/Libraries/LibWeb/Forward.h1
6 files changed, 120 insertions, 0 deletions
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
index 69b216a74a..a55787c6d0 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp
@@ -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();
diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
index febe81110b..a1ae0c5871 100644
--- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
+++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h
@@ -274,6 +274,7 @@ private:
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_content_value(Vector<StyleComponentValueRule> const&);
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&);
diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json
index 76b2980fee..4d72137c9c 100644
--- a/Userland/Libraries/LibWeb/CSS/Properties.json
+++ b/Userland/Libraries/LibWeb/CSS/Properties.json
@@ -510,6 +510,18 @@
"hashless-hex-color"
]
},
+ "content": {
+ "inherited": false,
+ "initial": "normal",
+ "__comment": "FIXME: This accepts a whole lot of other types and identifiers!",
+ "valid-types": [
+ "string"
+ ],
+ "valid-identifiers": [
+ "normal",
+ "none"
+ ]
+ },
"cursor": {
"inherited": true,
"initial": "auto",
diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp
index 61574be54c..0aab0d5ab4 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp
+++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp
@@ -81,6 +81,12 @@ ColorStyleValue const& StyleValue::as_color() const
return static_cast<ColorStyleValue const&>(*this);
}
+ContentStyleValue const& StyleValue::as_content() const
+{
+ VERIFY(is_content());
+ return static_cast<ContentStyleValue const&>(*this);
+}
+
FlexStyleValue const& StyleValue::as_flex() const
{
VERIFY(is_flex());
@@ -1015,6 +1021,13 @@ String CombinedBorderRadiusStyleValue::to_string() const
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());
}
+String ContentStyleValue::to_string() const
+{
+ if (has_alt_text())
+ return String::formatted("{} / {}", m_content->to_string(), m_alt_text->to_string());
+ return m_content->to_string();
+}
+
String FlexStyleValue::to_string() const
{
return String::formatted("{} {} {}", m_grow->to_string(), m_shrink->to_string(), m_basis->to_string());
diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h
index b98cf3ff19..ad09542f20 100644
--- a/Userland/Libraries/LibWeb/CSS/StyleValue.h
+++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h
@@ -297,6 +297,7 @@ public:
Calculated,
Color,
CombinedBorderRadius,
+ Content,
Flex,
FlexFlow,
Font,
@@ -333,6 +334,7 @@ public:
bool is_box_shadow() const { return type() == Type::BoxShadow; }
bool is_calculated() const { return type() == Type::Calculated; }
bool is_color() const { return type() == Type::Color; }
+ bool is_content() const { return type() == Type::Content; }
bool is_flex() const { return type() == Type::Flex; }
bool is_flex_flow() const { return type() == Type::FlexFlow; }
bool is_font() const { return type() == Type::Font; }
@@ -367,6 +369,7 @@ public:
BoxShadowStyleValue const& as_box_shadow() const;
CalculatedStyleValue const& as_calculated() const;
ColorStyleValue const& as_color() const;
+ ContentStyleValue const& as_content() const;
FlexFlowStyleValue const& as_flex_flow() const;
FlexStyleValue const& as_flex() const;
FontStyleValue const& as_font() const;
@@ -399,6 +402,7 @@ public:
BoxShadowStyleValue& as_box_shadow() { return const_cast<BoxShadowStyleValue&>(const_cast<StyleValue const&>(*this).as_box_shadow()); }
CalculatedStyleValue& as_calculated() { return const_cast<CalculatedStyleValue&>(const_cast<StyleValue const&>(*this).as_calculated()); }
ColorStyleValue& as_color() { return const_cast<ColorStyleValue&>(const_cast<StyleValue const&>(*this).as_color()); }
+ ContentStyleValue& as_content() { return const_cast<ContentStyleValue&>(const_cast<StyleValue const&>(*this).as_content()); }
FlexFlowStyleValue& as_flex_flow() { return const_cast<FlexFlowStyleValue&>(const_cast<StyleValue const&>(*this).as_flex_flow()); }
FlexStyleValue& as_flex() { return const_cast<FlexStyleValue&>(const_cast<StyleValue const&>(*this).as_flex()); }
FontStyleValue& as_font() { return const_cast<FontStyleValue&>(const_cast<StyleValue const&>(*this).as_font()); }
@@ -969,6 +973,31 @@ private:
NonnullRefPtr<BorderRadiusStyleValue> m_bottom_left;
};
+class ContentStyleValue final : public StyleValue {
+public:
+ static NonnullRefPtr<ContentStyleValue> create(NonnullRefPtr<StyleValueList> content, RefPtr<StyleValueList> alt_text)
+ {
+ return adopt_ref(*new ContentStyleValue(move(content), move(alt_text)));
+ }
+
+ StyleValueList const& content() const { return *m_content; }
+ bool has_alt_text() const { return !m_alt_text.is_null(); }
+ StyleValueList const* alt_text() const { return m_alt_text; }
+
+ virtual String to_string() const override;
+
+private:
+ ContentStyleValue(NonnullRefPtr<StyleValueList> content, RefPtr<StyleValueList> alt_text)
+ : StyleValue(Type::Content)
+ , m_content(move(content))
+ , m_alt_text(move(alt_text))
+ {
+ }
+
+ NonnullRefPtr<StyleValueList> m_content;
+ RefPtr<StyleValueList> m_alt_text;
+};
+
class FlexStyleValue final : public StyleValue {
public:
static NonnullRefPtr<FlexStyleValue> create(
diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h
index fbdadad579..e26f5f06da 100644
--- a/Userland/Libraries/LibWeb/Forward.h
+++ b/Userland/Libraries/LibWeb/Forward.h
@@ -30,6 +30,7 @@ class BorderStyleValue;
class BoxShadowStyleValue;
class CalculatedStyleValue;
class ColorStyleValue;
+class ContentStyleValue;
class CSSImportRule;
class CSSMediaRule;
class CSSRule;