From 343c48f5ad49d28953ae134b8071afcbe002b588 Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Wed, 8 Jan 2025 16:12:48 -0800 Subject: [PATCH] fix: viewBox translation by not accidentally stringifying literals (#3527) * fix: don't double stringify lits * also split off namespaces in translation --- packages/html/src/attribute_groups.rs | 4 +- packages/html/src/elements.rs | 2 +- packages/rsx-rosetta/src/lib.rs | 9 +++ packages/rsx-rosetta/tests/svgs.rs | 97 +++++++++++++++++++++++++++ 4 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 packages/rsx-rosetta/tests/svgs.rs diff --git a/packages/html/src/attribute_groups.rs b/packages/html/src/attribute_groups.rs index 273bb5888..fc456c196 100644 --- a/packages/html/src/attribute_groups.rs +++ b/packages/html/src/attribute_groups.rs @@ -63,7 +63,7 @@ macro_rules! html_to_rsx_attribute_mapping { $(#[$attr:meta])* $name:ident: $lit:literal; ) => { - if $matching == stringify!($lit) { + if $matching == $lit { return Some(stringify!($name)); } }; @@ -72,7 +72,7 @@ macro_rules! html_to_rsx_attribute_mapping { $(#[$attr:meta])* $name:ident: $lit:literal in $ns:literal; ) => { - if $matching == stringify!($lit) { + if $matching == $lit { return Some(stringify!($name)); } }; diff --git a/packages/html/src/elements.rs b/packages/html/src/elements.rs index ab3e6808a..ce92ae99c 100644 --- a/packages/html/src/elements.rs +++ b/packages/html/src/elements.rs @@ -188,7 +188,7 @@ macro_rules! impl_attribute_match { $attr:ident $fil:ident: $vil:ident (in $ns:literal), ) => { if $attr == stringify!($fil) { - return Some((stringify!(fil), Some($ns))); + return Some((stringify!($fil), Some($ns))); } }; } diff --git a/packages/rsx-rosetta/src/lib.rs b/packages/rsx-rosetta/src/lib.rs index fbfe197e6..85604a204 100644 --- a/packages/rsx-rosetta/src/lib.rs +++ b/packages/rsx-rosetta/src/lib.rs @@ -57,6 +57,10 @@ pub fn rsx_node_from_html(node: &Node) -> Option { .attributes .iter() .map(|(name, value)| { + // xlink attributes are deprecated and technically we can't handle them. + // todo(jon): apply the namespaces to the attributes + let (_namespace, name) = name.split_once(':').unwrap_or(("", name)); + let value = HotLiteral::from_raw_text(value.as_deref().unwrap_or("false")); let attr = if let Some(name) = map_html_attribute_to_rsx(name) { let name = if let Some(name) = name.strip_prefix("r#") { @@ -89,6 +93,11 @@ pub fn rsx_node_from_html(node: &Node) -> Option { )); } + // the html-parser crate we use uses a HashMap for attributes. This leads to a + // non-deterministic order of attributes. + // Sort them here + attributes.sort_by(|a, b| a.name.to_string().cmp(&b.name.to_string())); + let children = el.children.iter().filter_map(rsx_node_from_html).collect(); Some(BodyNode::Element(Element { diff --git a/packages/rsx-rosetta/tests/svgs.rs b/packages/rsx-rosetta/tests/svgs.rs new file mode 100644 index 000000000..6dc011292 --- /dev/null +++ b/packages/rsx-rosetta/tests/svgs.rs @@ -0,0 +1,97 @@ +use html_parser::Dom; + +#[test] +fn svgs() { + let viewbox = dioxus_html::map_html_attribute_to_rsx("viewBox"); + assert_eq!(viewbox, Some("view_box")); + + let html = r###" + + + + + +"###; + + let dom = Dom::parse(html).unwrap(); + + let body = dioxus_rsx_rosetta::rsx_from_html(&dom); + + let out = dioxus_autofmt::write_block_out(&body).unwrap(); + pretty_assertions::assert_eq!( + &out, + r##" + svg { + id: "flag-icons-fr", + view_box: "0 0 640 480", + xmlns: "http://www.w3.org/2000/svg", + path { d: "M0 0h640v480H0z", fill: "#fff" } + path { d: "M0 0h213.3v480H0z", fill: "#000091" } + path { d: "M426.7 0H640v480H426.7z", fill: "#e1000f" } + }"## + ); + + let html = r###" + + + + + + + + + + + + "###; + + let dom = Dom::parse(html).unwrap(); + + let body = dioxus_rsx_rosetta::rsx_from_html(&dom); + + let out = dioxus_autofmt::write_block_out(&body).unwrap(); + pretty_assertions::assert_eq!( + &out, + r##" + svg { + id: "flag-icons-cn", + view_box: "0 0 640 480", + "xlink": "http://www.w3.org/1999/xlink", + xmlns: "http://www.w3.org/2000/svg", + defs { + path { d: "M-.6.8 0-1 .6.8-1-.3h2z", fill: "#ff0", id: "cn-a" } + } + path { d: "M0 0h640v480H0z", fill: "#ee1c25" } + use { + height: "20", + href: "#cn-a", + transform: "matrix(71.9991 0 0 72 120 120)", + width: "30", + } + use { + height: "20", + href: "#cn-a", + transform: "matrix(-12.33562 -20.5871 20.58684 -12.33577 240.3 48)", + width: "30", + } + use { + height: "20", + href: "#cn-a", + transform: "matrix(-3.38573 -23.75998 23.75968 -3.38578 288 95.8)", + width: "30", + } + use { + height: "20", + href: "#cn-a", + transform: "matrix(6.5991 -23.0749 23.0746 6.59919 288 168)", + width: "30", + } + use { + height: "20", + href: "#cn-a", + transform: "matrix(14.9991 -18.73557 18.73533 14.99929 240 216)", + width: "30", + } + }"## + ); +}