diff --git a/Cargo.toml b/Cargo.toml index bc76153..34b73c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "svg" -version = "0.15.1" +version = "0.16.0" edition = "2021" license = "Apache-2.0/MIT" authors = [ diff --git a/src/node/element/mod.rs b/src/node/element/mod.rs index dcb75d8..08a58c0 100644 --- a/src/node/element/mod.rs +++ b/src/node/element/mod.rs @@ -76,10 +76,18 @@ impl fmt::Display for Element { return write!(formatter, "/>"); } write!(formatter, ">")?; + let mut bare = false; for child in self.children.iter() { - write!(formatter, "\n{}", child)?; + bare = child.is_bare() && !formatter.alternate(); + if !bare { + writeln!(formatter)?; + } + write!(formatter, "{}", child)?; + } + if !bare { + writeln!(formatter)?; } - write!(formatter, "\n", self.name) + write!(formatter, "", self.name) } } @@ -310,18 +318,9 @@ implement! { #[doc = "A [`symbol`](https://www.w3.org/TR/SVG/struct.html#SymbolElement) element."] struct Symbol - #[doc = "A [`text`](https://www.w3.org/TR/SVG/text.html#TextElement) element."] - struct Text - #[doc = "A [`textPath`](https://www.w3.org/TR/SVG/text.html#TextPathElement) element."] struct TextPath - #[doc = "A [`title`](https://www.w3.org/TR/SVG/struct.html#TitleElement) element."] - struct Title - - #[doc = "A [`tspan`](https://www.w3.org/TR/SVG/text.html#TextElement) element."] - struct TSpan - #[doc = "A [`use`](https://www.w3.org/TR/SVG/struct.html#UseElement) element."] struct Use } @@ -331,7 +330,9 @@ macro_rules! implement { ($( #[$doc:meta] struct $struct_name:ident - [$($pn:ident: $($pt:tt)*),*] [$inner:ident $(,$an:ident: $at:ty)*] $body:block + [$($indicator_name:ident),*] + [$($trait_name:ident: $($trait_type:tt)*),*] + [$inner:ident $(,$argument_name:ident: $argument_type:ty)*] $body:block )*) => ($( #[$doc] #[derive(Clone, Debug)] @@ -343,11 +344,13 @@ macro_rules! implement { impl $struct_name { /// Create a node. #[inline] - pub fn new<$($pn: $($pt)*),*>($($an: $at),*) -> Self { + pub fn new<$($trait_name: $($trait_type)*),*>($($argument_name: $argument_type),*) -> Self { #[inline(always)] - fn initialize<$($pn: $($pt)*),*>($inner: &mut Element $(, $an: $at)*) $body + fn initialize<$($trait_name: $($trait_type)*),*>( + $inner: &mut Element $(, $argument_name: $argument_type)* + ) $body let mut inner = Element::new(tag::$struct_name); - initialize(&mut inner $(, $an)*); + initialize(&mut inner $(, $argument_name)*); $struct_name { inner, } @@ -361,23 +364,38 @@ macro_rules! implement { } } - node! { $struct_name::inner } + node! { $struct_name::inner [$($indicator_name),*] } )*); } implement! { + #[doc = "A [`text`](https://www.w3.org/TR/SVG/text.html#TextElement) element."] + struct Text [is_bareable] [T: Into] [inner, content: T] { + inner.append(crate::node::Text::new(content)); + } + + #[doc = "A [`title`](https://www.w3.org/TR/SVG/struct.html#TitleElement) element."] + struct Title [] [T: Into] [inner, content: T] { + inner.append(crate::node::Text::new(content)); + } + + #[doc = "A [`tspan`](https://www.w3.org/TR/SVG/text.html#TextElement) element."] + struct TSpan [] [T: Into] [inner, content: T] { + inner.append(crate::node::Text::new(content)); + } + #[doc = "An [`svg`](https://www.w3.org/TR/SVG/struct.html#SVGElement) element."] - struct SVG [] [inner] { + struct SVG [is_bareable] [] [inner] { inner.assign("xmlns", "http://www.w3.org/2000/svg"); } #[doc = "A [`script`](https://www.w3.org/TR/SVG/script.html#ScriptElement) element."] - struct Script [T: Into] [inner, content: T] { + struct Script [is_bareable] [T: Into] [inner, content: T] { inner.append(crate::node::Text::new(content)); } #[doc = "A [`style`](https://www.w3.org/TR/SVG/styling.html#StyleElement) element."] - struct Style [T: Into] [inner, content: T] { + struct Style [is_bareable] [T: Into] [inner, content: T] { inner.append(crate::node::Text::new(content)); } } @@ -391,14 +409,14 @@ fn escape(value: &str) -> String { #[cfg(test)] mod tests { use super::{Element, Rectangle, Style, Title}; - use crate::node::{self, element, Node}; + use crate::node::{element, Node}; #[test] fn element_children() { let mut one = element::Group::new() - .add(element::Text::new().add(node::Text::new("foo"))) - .add(element::Text::new().add(node::Text::new("bar"))) - .add(element::Text::new().add(node::Text::new("buz"))); + .add(element::Text::new("foo")) + .add(element::Text::new("bar")) + .add(element::Text::new("buz")); let two = element::Group::new() .add(one.get_children()[0].clone()) .add(one.get_children_mut().pop().unwrap()); @@ -440,15 +458,13 @@ mod tests { .set("width", 0.3088995) .set("x", 328.0725) .set("y", 120) - .add(Title::new().add(node::Text::new("widgets >=3.0.9, <3.1.dev0"))); + .add(Title::new("widgets >=3.0.9, <3.1.dev0")); assert_eq!( element.to_string().lines().collect::>(), &[ r###""###, - "", - "widgets >=3.0.9, <3.1.dev0", - "", + "widgets >=3.0.9, <3.1.dev0", "", ], ); diff --git a/src/node/mod.rs b/src/node/mod.rs index 98fced6..6f127c2 100644 --- a/src/node/mod.rs +++ b/src/node/mod.rs @@ -42,6 +42,16 @@ pub trait Node: U: Into, { } + + #[doc(hidden)] + fn is_bare(&self) -> bool { + false + } + + #[doc(hidden)] + fn is_bareable(&self) -> bool { + false + } } #[doc(hidden)] @@ -90,6 +100,9 @@ impl NodeDefaultHash for Box { macro_rules! node( ($struct_name:ident::$field_name:ident) => ( + node!($struct_name::$field_name []); + ); + ($struct_name:ident::$field_name:ident [$($indicator_name:ident),*]) => ( impl $struct_name { /// Append a node. pub fn add(mut self, node: T) -> Self @@ -129,6 +142,13 @@ macro_rules! node( { self.$field_name.assign(name, value); } + + $( + #[inline] + fn $indicator_name(&self) -> bool { + true + } + )* } impl ::std::ops::Deref for $struct_name { @@ -150,7 +170,11 @@ macro_rules! node( impl ::std::fmt::Display for $struct_name { #[inline] fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { - self.$field_name.fmt(formatter) + if self.is_bareable() { + write!(formatter, "{:#}", self.$field_name) + } else { + self.$field_name.fmt(formatter) + } } } diff --git a/src/node/text.rs b/src/node/text.rs index f5ecda4..0a47a41 100644 --- a/src/node/text.rs +++ b/src/node/text.rs @@ -30,7 +30,12 @@ impl fmt::Display for Text { } } -impl Node for Text {} +impl Node for Text { + #[inline] + fn is_bare(&self) -> bool { + true + } +} impl super::NodeDefaultHash for Text { #[inline]