diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 354035f149..0e2e201042 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -523,6 +523,7 @@ set(SOURCES SVG/SVGRadialGradientElement.cpp SVG/SVGSVGElement.cpp SVG/SVGStopElement.cpp + SVG/SVGStyleElement.cpp SVG/SVGSymbolElement.cpp SVG/SVGTextContentElement.cpp SVG/SVGTitleElement.cpp diff --git a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp index d63b9aeb9b..5c11be7abc 100644 --- a/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp +++ b/Userland/Libraries/LibWeb/DOM/ElementFactory.cpp @@ -97,6 +97,7 @@ #include #include #include +#include #include #include #include @@ -456,6 +457,8 @@ static WebIDL::ExceptionOr> create_svg_element(JS::Re return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::stop) return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); + if (local_name == SVG::TagNames::style) + return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::symbol) return MUST_OR_THROW_OOM(realm.heap().allocate(realm, document, move(qualified_name))); if (local_name == SVG::TagNames::text) diff --git a/Userland/Libraries/LibWeb/SVG/SVGStyleElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.cpp new file mode 100644 index 0000000000..6f12a81647 --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2023, Preston Taylor + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include + +namespace Web::SVG { + +SVGStyleElement::SVGStyleElement(DOM::Document& document, DOM::QualifiedName qualified_name) + : SVGElement(document, move(qualified_name)) +{ +} + +SVGStyleElement::~SVGStyleElement() = default; + +JS::ThrowCompletionOr SVGStyleElement::initialize(JS::Realm& realm) +{ + MUST_OR_THROW_OOM(Base::initialize(realm)); + set_prototype(&Bindings::ensure_web_prototype(realm, "SVGStyleElement")); + + return {}; +} + +void SVGStyleElement::visit_edges(Cell::Visitor& visitor) +{ + Base::visit_edges(visitor); + visitor.visit(m_style_element_utils.sheet()); +} + +void SVGStyleElement::children_changed() +{ + m_style_element_utils.update_a_style_block(*this); + Base::children_changed(); +} + +void SVGStyleElement::inserted() +{ + m_style_element_utils.update_a_style_block(*this); + Base::inserted(); +} + +void SVGStyleElement::removed_from(Node* old_parent) +{ + m_style_element_utils.update_a_style_block(*this); + Base::removed_from(old_parent); +} + +// https://www.w3.org/TR/cssom/#dom-linkstyle-sheet +CSS::CSSStyleSheet* SVGStyleElement::sheet() +{ + // The sheet attribute must return the associated CSS style sheet for the node or null if there is no associated CSS style sheet. + return m_style_element_utils.sheet(); +} + +// https://www.w3.org/TR/cssom/#dom-linkstyle-sheet +CSS::CSSStyleSheet const* SVGStyleElement::sheet() const +{ + // The sheet attribute must return the associated CSS style sheet for the node or null if there is no associated CSS style sheet. + return m_style_element_utils.sheet(); +} + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGStyleElement.h b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.h new file mode 100644 index 0000000000..1d4a53d1cc --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023, Preston Taylor + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include +#include + +namespace Web::SVG { + +class SVGStyleElement final : public SVGElement { + WEB_PLATFORM_OBJECT(HTMLStyleElement, SVGElement); + +public: + virtual ~SVGStyleElement() override; + + virtual void children_changed() override; + virtual void inserted() override; + virtual void removed_from(Node*) override; + + CSS::CSSStyleSheet* sheet(); + CSS::CSSStyleSheet const* sheet() const; + +private: + SVGStyleElement(DOM::Document&, DOM::QualifiedName); + + virtual JS::ThrowCompletionOr initialize(JS::Realm&) override; + virtual void visit_edges(Cell::Visitor&) override; + + // The semantics and processing of a ‘style’ and its attributes must be the same as is defined for the HTML ‘style’ element. + DOM::StyleElementUtils m_style_element_utils; +}; + +} diff --git a/Userland/Libraries/LibWeb/SVG/SVGStyleElement.idl b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.idl new file mode 100644 index 0000000000..b1fcd5f7ba --- /dev/null +++ b/Userland/Libraries/LibWeb/SVG/SVGStyleElement.idl @@ -0,0 +1,11 @@ +#import +#import + +[Exposed=Window] +interface SVGStyleElement : SVGElement { + [Reflect] attribute DOMString type; + [Reflect] attribute DOMString media; + [Reflect] attribute DOMString title; +}; + +SVGStyleElement includes LinkStyle; diff --git a/Userland/Libraries/LibWeb/SVG/TagNames.h b/Userland/Libraries/LibWeb/SVG/TagNames.h index 36887a0d4b..963a00db9e 100644 --- a/Userland/Libraries/LibWeb/SVG/TagNames.h +++ b/Userland/Libraries/LibWeb/SVG/TagNames.h @@ -33,6 +33,7 @@ namespace Web::SVG::TagNames { __ENUMERATE_SVG_TAG(radialGradient) \ __ENUMERATE_SVG_TAG(script) \ __ENUMERATE_SVG_TAG(stop) \ + __ENUMERATE_SVG_TAG(style) \ __ENUMERATE_SVG_TAG(symbol) \ __ENUMERATE_SVG_TAG(title) \ __ENUMERATE_SVG_TAG(use) diff --git a/Userland/Libraries/LibWeb/idl_files.cmake b/Userland/Libraries/LibWeb/idl_files.cmake index 4396976183..01e56a75be 100644 --- a/Userland/Libraries/LibWeb/idl_files.cmake +++ b/Userland/Libraries/LibWeb/idl_files.cmake @@ -211,6 +211,7 @@ libweb_js_bindings(SVG/SVGRadialGradientElement) libweb_js_bindings(SVG/SVGRectElement) libweb_js_bindings(SVG/SVGSVGElement) libweb_js_bindings(SVG/SVGStopElement) +libweb_js_bindings(SVG/SVGStyleElement) libweb_js_bindings(SVG/SVGSymbolElement) libweb_js_bindings(SVG/SVGTextContentElement) libweb_js_bindings(SVG/SVGTitleElement)