use itertools::Itertools;
use oxvg_ast::{
element::Element,
visitor::{Context, Visitor},
};
use oxvg_collections::content_type::{ContentType, ContentTypeRef};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[cfg(feature = "wasm")]
use tsify::Tsify;
use crate::error::JobsError;
#[cfg_attr(feature = "wasm", derive(Tsify))]
#[cfg_attr(feature = "napi", napi(object))]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, Clone)]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct CleanupAttrs {
#[cfg_attr(feature = "serde", serde(default = "newlines_default"))]
pub newlines: bool,
#[cfg_attr(feature = "serde", serde(default = "trim_default"))]
pub trim: bool,
#[cfg_attr(feature = "serde", serde(default = "spaces_default"))]
pub spaces: bool,
}
impl<'input, 'arena> Visitor<'input, 'arena> for CleanupAttrs {
type Error = JobsError<'input>;
fn element(
&self,
element: &Element<'input, 'arena>,
_context: &mut Context<'input, 'arena, '_>,
) -> Result<(), Self::Error> {
for mut attr in element.attributes().into_iter_mut() {
let ContentType::Anything(ContentTypeRef::RefMut(value)) = attr.value_mut() else {
continue;
};
if self.newlines {
*value = value.replace('\n', " ").into();
}
if self.trim {
*value = value.trim().to_string().into();
}
if self.spaces {
*value = value.split_whitespace().join(" ").into();
}
}
Ok(())
}
}
impl Default for CleanupAttrs {
fn default() -> Self {
Self {
newlines: newlines_default(),
trim: trim_default(),
spaces: spaces_default(),
}
}
}
const fn newlines_default() -> bool {
true
}
const fn trim_default() -> bool {
true
}
const fn spaces_default() -> bool {
true
}
#[test]
fn cleanup_attrs() -> anyhow::Result<()> {
use crate::test_config;
insta::assert_snapshot!(test_config(
r#"{ "cleanupAttrs": {
"newlines": true,
"trim": true,
"spaces": true
} }"#,
Some(
r#"<svg xmlns=" http://www.w3.org/2000/svg
" attr="a b" attr2="a
b">
<!-- Should remove all unnecessary whitespace from attributes -->
test
</svg>"#
)
)?);
insta::assert_snapshot!(test_config(
r#"{ "cleanupAttrs": {
"newlines": true,
"trim": true,
"spaces": true
} }"#,
Some(
r#"<svg xmlns=" http://www.w3.org/2000/svg
" attr="a b">
<!-- Should remove all unnecessary whitespace from attributes -->
test & <& > ' " &
</svg>"#
)
)?);
Ok(())
}