diff --git a/crates/core/__fixture__/plugins/convertEllipseToCircle.01.svg b/crates/core/__fixture__/plugins/convertEllipseToCircle.01.svg
new file mode 100644
index 0000000..6e3ce03
--- /dev/null
+++ b/crates/core/__fixture__/plugins/convertEllipseToCircle.01.svg
@@ -0,0 +1,15 @@
+
+
+@@@
+
+
diff --git a/crates/core/src/plugins/convert_ellipse_to_circle.rs b/crates/core/src/plugins/convert_ellipse_to_circle.rs
new file mode 100644
index 0000000..4840922
--- /dev/null
+++ b/crates/core/src/plugins/convert_ellipse_to_circle.rs
@@ -0,0 +1,84 @@
+// Converts non-eccentric s to s.
+
+use swc_core::common::DUMMY_SP;
+use swc_xml_ast::*;
+use swc_xml_visit::{VisitMut, VisitMutWith};
+use serde::Deserialize;
+
+struct Visitor {}
+
+#[derive(Debug, Deserialize)]
+#[serde(rename_all = "camelCase")]
+pub struct Params {}
+
+impl Default for Params {
+ fn default() -> Self {
+ Self {}
+ }
+}
+
+impl Visitor {
+ fn new() -> Self {
+ Self {}
+ }
+}
+
+impl VisitMut for Visitor {
+ fn visit_mut_element(&mut self, n: &mut Element) {
+ if n.tag_name.to_string() == "ellipse" {
+ let mut rx = "0".to_string();
+ let mut ry = "0".to_string();
+ let mut new_attributes = vec![];
+ for attr in n.attributes.clone() {
+ if attr.name.to_string() == "rx" {
+ if let Some(value) = attr.value.clone() {
+ rx = value.to_string();
+ }
+ } else if attr.name.to_string() == "ry" {
+ if let Some(value) = attr.value.clone() {
+ ry = value.to_string();
+ }
+ } else {
+ new_attributes.push(attr);
+ }
+ }
+
+ if rx == ry ||
+ rx == "auto" ||
+ ry == "auto" // SVG2
+ {
+ n.tag_name = "circle".to_string().into();
+ let radius = if rx == "auto" { ry } else { rx };
+ new_attributes.push(Attribute {
+ span: DUMMY_SP,
+ namespace: None,
+ prefix: None,
+ name: "r".to_string().into(),
+ raw_name: None,
+ value: Some(radius.into()),
+ raw_value: None,
+ });
+ n.attributes = new_attributes;
+ }
+ }
+ n.visit_mut_children_with(self);
+ }
+}
+
+pub fn apply(doc: &mut Document, _: &Params) {
+ let mut v = Visitor::new();
+ doc.visit_mut_with(&mut v);
+}
+
+#[cfg(test)]
+mod tests {
+ use std::path::PathBuf;
+
+ use crate::testing::test_plugin;
+ use super::*;
+
+ #[testing::fixture("__fixture__/plugins/convertEllipseToCircle.*.svg")]
+ fn pass(input: PathBuf) {
+ test_plugin(apply, input);
+ }
+}
diff --git a/crates/core/src/plugins/mod.rs b/crates/core/src/plugins/mod.rs
index 83a61dc..b28b44e 100644
--- a/crates/core/src/plugins/mod.rs
+++ b/crates/core/src/plugins/mod.rs
@@ -4,3 +4,4 @@ pub mod cleanup_ids;
pub mod cleanup_numeric_values;
pub mod collapse_groups;
pub mod convert_colors;
+pub mod convert_ellipse_to_circle;