writer.write_event(Event::Text(BytesText::new(&format!("&[{name}]"))))?
}
Markup::Style { style, child } => {
- match style {
- Style::Bold => writer.create_element("b"),
- Style::Italic => writer.create_element("i"),
- Style::Underline => writer.create_element("u"),
- Style::Strike => writer.create_element("strike"),
- Style::Emphasis => writer.create_element("em"),
- Style::Strong => writer.create_element("strong"),
- Style::Face(face) => writer
- .create_element("font")
- .with_attribute(("face", face.as_str())),
- Style::Color(color) => writer
- .create_element("font")
- .with_attribute(("color", color.display_css().to_string().as_str())),
- Style::Size(points) => writer
- .create_element("font")
- .with_attribute(("size", format!("{}pt", *points / 0.75).as_str())),
+ let mut elements = Vec::new();
+ let mut attributes = Vec::new();
+ fn add_style(
+ style: &Style,
+ elements: &mut Vec<&'static str>,
+ attributes: &mut Vec<(&'static str, String)>,
+ ) {
+ match style {
+ Style::Bold => elements.push("b"),
+ Style::Italic => elements.push("i"),
+ Style::Underline => elements.push("u"),
+ Style::Strike => elements.push("strike"),
+ Style::Emphasis => elements.push("em"),
+ Style::Strong => elements.push("strong"),
+ Style::Face(face) => attributes.push(("face", face.clone())),
+ Style::Color(color) => {
+ attributes.push(("color", color.display_css().to_string()))
+ }
+ Style::Size(points) => {
+ attributes.push(("size", format!("{}pt", *points / 0.75)))
+ }
+ }
}
- .write_inner_content(|w| child.write_html(w))?;
+
+ add_style(style, &mut elements, &mut attributes);
+ let mut next = &**child;
+ while let Markup::Style { style, child } = next {
+ add_style(style, &mut elements, &mut attributes);
+ next = &**child;
+ }
+
+ elements.sort();
+ attributes.sort();
+ next.write_styles(writer, &elements, &attributes)?;
}
}
Ok(())
}
+ fn write_styles<X>(
+ &self,
+ writer: &mut XmlWriter<X>,
+ elements: &[&str],
+ attributes: &[(&str, String)],
+ ) -> std::io::Result<()>
+ where
+ X: Write,
+ {
+ if !attributes.is_empty() {
+ writer
+ .create_element("font")
+ .with_attributes(
+ attributes
+ .into_iter()
+ .map(|(name, value)| (*name, Cow::from(value))),
+ )
+ .write_inner_content(|w| self.write_styles(w, elements, &[]))?;
+ } else if let Some((element, rest)) = elements.split_first() {
+ writer
+ .create_element(*element)
+ .write_inner_content(|w| self.write_styles(w, rest, attributes))?;
+ } else {
+ self.write_html(writer)?;
+ }
+ Ok(())
+ }
+
/// Returns this markup converted into XHTML. The returned string contains
/// a single `<html>...</html>` element.
///
let content = quick_xml::de::from_str::<String>(text).unwrap();
assert_eq!(
Document::from_html(&content).to_html(),
- r##"<p align="left">plain <font size="9pt"><font color="#000000"><font face="Monospaced"><b>bold</b></font></font></font> <font size="9pt"><font color="#000000"><font face="Monospaced"><i>italic</i> <strike>strikeout</strike></font></font></font></p>"##
+ r##"<p align="left">plain <font color="#000000" face="Monospaced" size="9pt"><b>bold</b></font> <font color="#000000" face="Monospaced" size="9pt"><i>italic</i> <strike>strikeout</strike></font></p>"##
);
}
let content = quick_xml::de::from_str::<String>(text).unwrap();
assert_eq!(
Document::from_html(&content).to_html(),
- r##"<p align="left">left</p><p align="center"><font size="13.5pt"><font color="#000000"><font face="Monospaced">center large</font></font></font></p><p align="right"><font size="9pt"><font color="#000000"><font face="Monospaced"><b><i>right</i></b></font></font></font></p>"##
+ r##"<p align="left">left</p><p align="center"><font color="#000000" face="Monospaced" size="13.5pt">center large</font></p><p align="right"><font color="#000000" face="Monospaced" size="9pt"><b><i>right</i></b></font></p>"##
);
}
let document = Document::from_html(&content);
assert_eq!(
document.to_html(),
- r##"<p align="center"><font color="#000000"><font size="10pt"><font face="sans-serif">&[PageTitle]</font></font></font></p>"##
+ r##"<p align="center"><font color="#000000" face="sans-serif" size="10pt">&[PageTitle]</font></p>"##
);
assert_eq!(
document.0[0]
let html = Document::from_html(&content);
assert_eq!(
html.to_html(),
- r##"<p align="right"><font color="#000000"><font size="10pt"><font face="sans-serif">Page &[Page]</font></font></font></p>"##
+ r##"<p align="right"><font color="#000000" face="sans-serif" size="10pt">Page &[Page]</font></p>"##
);
}