diff --git a/Tests/LibWeb/Text/expected/SVG/svg-className-attribute.txt b/Tests/LibWeb/Text/expected/SVG/svg-className-attribute.txt
new file mode 100644
index 00000000000..32903436987
--- /dev/null
+++ b/Tests/LibWeb/Text/expected/SVG/svg-className-attribute.txt
@@ -0,0 +1 @@
+ svg.className = 'demo class'
diff --git a/Tests/LibWeb/Text/input/SVG/svg-className-attribute.html b/Tests/LibWeb/Text/input/SVG/svg-className-attribute.html
new file mode 100644
index 00000000000..9d79807ba59
--- /dev/null
+++ b/Tests/LibWeb/Text/input/SVG/svg-className-attribute.html
@@ -0,0 +1,8 @@
+
+
+
diff --git a/Userland/Libraries/LibWeb/SVG/AttributeNames.cpp b/Userland/Libraries/LibWeb/SVG/AttributeNames.cpp
index dafe3a700e8..37f1d9a962c 100644
--- a/Userland/Libraries/LibWeb/SVG/AttributeNames.cpp
+++ b/Userland/Libraries/LibWeb/SVG/AttributeNames.cpp
@@ -22,6 +22,9 @@ void initialize_strings()
ENUMERATE_SVG_ATTRIBUTES(__ENUMERATE_SVG_ATTRIBUTE)
#undef __ENUMERATE_SVG_ATTRIBUTE
+ // NOTE: Special cases for C++ keywords.
+ class_ = "class"_fly_string;
+
// NOTE: Special case for attributes with ':' in them.
xlink_href = "xlink:href"_fly_string;
diff --git a/Userland/Libraries/LibWeb/SVG/AttributeNames.h b/Userland/Libraries/LibWeb/SVG/AttributeNames.h
index 9dcee9aa057..e9633d03b0e 100644
--- a/Userland/Libraries/LibWeb/SVG/AttributeNames.h
+++ b/Userland/Libraries/LibWeb/SVG/AttributeNames.h
@@ -17,6 +17,7 @@ namespace Web::SVG::AttributeNames {
E(baseFrequency) \
E(baseProfile) \
E(calcMode) \
+ E(class_) \
E(clipPathUnits) \
E(contentScriptType) \
E(contentStyleType) \
diff --git a/Userland/Libraries/LibWeb/SVG/SVGElement.cpp b/Userland/Libraries/LibWeb/SVG/SVGElement.cpp
index 158c2db357c..1226535db8e 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGElement.cpp
+++ b/Userland/Libraries/LibWeb/SVG/SVGElement.cpp
@@ -32,6 +32,7 @@ void SVGElement::visit_edges(Cell::Visitor& visitor)
{
Base::visit_edges(visitor);
visitor.visit(m_dataset);
+ visitor.visit(m_class_name_animated_string);
}
JS::NonnullGCPtr SVGElement::dataset()
@@ -114,6 +115,16 @@ void SVGElement::blur()
dbgln("(STUBBED) SVGElement::blur()");
}
+// https://svgwg.org/svg2-draft/types.html#__svg__SVGElement__classNames
+JS::NonnullGCPtr SVGElement::class_name()
+{
+ // The className IDL attribute reflects the ‘class’ attribute.
+ if (!m_class_name_animated_string)
+ m_class_name_animated_string = SVGAnimatedString::create(realm(), *this, AttributeNames::class_);
+
+ return *m_class_name_animated_string;
+}
+
JS::NonnullGCPtr SVGElement::svg_animated_length_for_property(CSS::PropertyID property) const
{
// FIXME: Create a proper animated value when animations are supported.
diff --git a/Userland/Libraries/LibWeb/SVG/SVGElement.h b/Userland/Libraries/LibWeb/SVG/SVGElement.h
index d14a2e19380..6dd10577657 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGElement.h
+++ b/Userland/Libraries/LibWeb/SVG/SVGElement.h
@@ -8,6 +8,7 @@
#include
#include
+#include
namespace Web::SVG {
@@ -30,6 +31,8 @@ public:
void focus();
void blur();
+ JS::NonnullGCPtr class_name();
+
protected:
SVGElement(DOM::Document&, DOM::QualifiedName);
@@ -48,6 +51,8 @@ private:
virtual JS::GCPtr global_event_handlers_to_event_target(FlyString const&) override { return *this; }
virtual bool is_svg_element() const final { return true; }
+
+ JS::GCPtr m_class_name_animated_string;
};
}
diff --git a/Userland/Libraries/LibWeb/SVG/SVGElement.idl b/Userland/Libraries/LibWeb/SVG/SVGElement.idl
index f3a2493abaf..cdad3c93929 100644
--- a/Userland/Libraries/LibWeb/SVG/SVGElement.idl
+++ b/Userland/Libraries/LibWeb/SVG/SVGElement.idl
@@ -2,10 +2,13 @@
#import
#import
#import
+#import