ladybird/Libraries/LibWeb/CSS/CSSStyleDeclaration.h
Luke Wilde aacf9b08ed LibWeb: Generate IDL attributes for all supported CSS properties
The CSSOM spec tells us to potentially add up to three different IDL
attributes to CSSStyleDeclaration for every CSS property we support:
- A camelCased attribute, where a dash indicates the next character
  should be uppercase
- A camelCased attribute for every -webkit- prefixed property, with the
  first letter always being lowercase
- A dashed-attribute for every property with a dash in it.

Additionally, every attribute must have the CEReactions and
LegacyNullToEmptyString extended attributes specified on it.

Since we specify every property we support with Properties.json, we can
use that file to generate the IDL file and it's implementation.

We import it from the Build directory with the help of multiple import
base paths. Then, we add it to CSSStyleDeclaration via the mixin
functionality and inheriting the generated class in
CSSStyleDeclaration.
2024-11-14 19:50:22 +01:00

140 lines
5.2 KiB
C++

/*
* Copyright (c) 2018-2023, Andreas Kling <andreas@ladybird.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#pragma once
#include <AK/String.h>
#include <AK/Vector.h>
#include <LibWeb/Bindings/PlatformObject.h>
#include <LibWeb/CSS/CSSStyleValue.h>
#include <LibWeb/CSS/GeneratedCSSStyleProperties.h>
#include <LibWeb/CSS/StyleProperty.h>
namespace Web::CSS {
class CSSStyleDeclaration
: public Bindings::PlatformObject
, public Bindings::GeneratedCSSStyleProperties {
WEB_PLATFORM_OBJECT(CSSStyleDeclaration, Bindings::PlatformObject);
JS_DECLARE_ALLOCATOR(CSSStyleDeclaration);
public:
virtual ~CSSStyleDeclaration() = default;
virtual void initialize(JS::Realm&) override;
virtual size_t length() const = 0;
virtual String item(size_t index) const = 0;
virtual Optional<StyleProperty> property(PropertyID) const = 0;
virtual WebIDL::ExceptionOr<void> set_property(PropertyID, StringView css_text, StringView priority = ""sv) = 0;
virtual WebIDL::ExceptionOr<String> remove_property(PropertyID) = 0;
virtual WebIDL::ExceptionOr<void> set_property(StringView property_name, StringView css_text, StringView priority);
virtual WebIDL::ExceptionOr<String> remove_property(StringView property_name);
String get_property_value(StringView property) const;
StringView get_property_priority(StringView property) const;
String css_text() const;
virtual WebIDL::ExceptionOr<void> set_css_text(StringView) = 0;
String css_float() const;
WebIDL::ExceptionOr<void> set_css_float(StringView);
virtual String serialized() const = 0;
virtual JS::GCPtr<CSSRule> parent_rule() const;
protected:
explicit CSSStyleDeclaration(JS::Realm&);
virtual CSSStyleDeclaration& generated_style_properties_to_css_style_declaration() override { return *this; }
private:
// ^PlatformObject
virtual Optional<JS::Value> item_value(size_t index) const override;
};
class PropertyOwningCSSStyleDeclaration : public CSSStyleDeclaration {
WEB_PLATFORM_OBJECT(PropertyOwningCSSStyleDeclaration, CSSStyleDeclaration);
JS_DECLARE_ALLOCATOR(PropertyOwningCSSStyleDeclaration);
friend class ElementInlineCSSStyleDeclaration;
public:
[[nodiscard]] static JS::NonnullGCPtr<PropertyOwningCSSStyleDeclaration>
create(JS::Realm&, Vector<StyleProperty>, HashMap<FlyString, StyleProperty> custom_properties);
virtual ~PropertyOwningCSSStyleDeclaration() override = default;
virtual size_t length() const override;
virtual String item(size_t index) const override;
virtual Optional<StyleProperty> property(PropertyID) const override;
virtual WebIDL::ExceptionOr<void> set_property(PropertyID, StringView css_text, StringView priority) override;
virtual WebIDL::ExceptionOr<String> remove_property(PropertyID) override;
Vector<StyleProperty> const& properties() const { return m_properties; }
HashMap<FlyString, StyleProperty> const& custom_properties() const { return m_custom_properties; }
Optional<StyleProperty> custom_property(FlyString const& custom_property_name) const { return m_custom_properties.get(custom_property_name); }
size_t custom_property_count() const { return m_custom_properties.size(); }
virtual String serialized() const final override;
virtual WebIDL::ExceptionOr<void> set_css_text(StringView) override;
virtual JS::GCPtr<CSSRule> parent_rule() const override;
void set_parent_rule(JS::NonnullGCPtr<CSSRule>);
protected:
PropertyOwningCSSStyleDeclaration(JS::Realm&, Vector<StyleProperty>, HashMap<FlyString, StyleProperty>);
virtual void update_style_attribute() { }
void empty_the_declarations();
void set_the_declarations(Vector<StyleProperty> properties, HashMap<FlyString, StyleProperty> custom_properties);
private:
bool set_a_css_declaration(PropertyID, NonnullRefPtr<CSSStyleValue const>, Important);
virtual void visit_edges(Cell::Visitor&) override;
JS::GCPtr<CSSRule> m_parent_rule;
Vector<StyleProperty> m_properties;
HashMap<FlyString, StyleProperty> m_custom_properties;
};
class ElementInlineCSSStyleDeclaration final : public PropertyOwningCSSStyleDeclaration {
WEB_PLATFORM_OBJECT(ElementInlineCSSStyleDeclaration, PropertyOwningCSSStyleDeclaration);
JS_DECLARE_ALLOCATOR(ElementInlineCSSStyleDeclaration);
public:
[[nodiscard]] static JS::NonnullGCPtr<ElementInlineCSSStyleDeclaration> create(DOM::Element&, Vector<StyleProperty>, HashMap<FlyString, StyleProperty> custom_properties);
virtual ~ElementInlineCSSStyleDeclaration() override = default;
DOM::Element* element() { return m_element.ptr(); }
const DOM::Element* element() const { return m_element.ptr(); }
bool is_updating() const { return m_updating; }
virtual WebIDL::ExceptionOr<void> set_css_text(StringView) override;
private:
ElementInlineCSSStyleDeclaration(DOM::Element&, Vector<StyleProperty> properties, HashMap<FlyString, StyleProperty> custom_properties);
virtual void visit_edges(Cell::Visitor&) override;
virtual void update_style_attribute() override;
JS::GCPtr<DOM::Element> m_element;
// https://drafts.csswg.org/cssom/#cssstyledeclaration-updating-flag
bool m_updating { false };
};
}