2020-04-07 04:24:56 +03:00
|
|
|
#![allow(clippy::single_match)]
|
|
|
|
|
2020-02-11 10:01:39 +02:00
|
|
|
use std::io::Read;
|
|
|
|
use std::str::FromStr;
|
|
|
|
|
|
|
|
use xml::attribute::OwnedAttribute;
|
|
|
|
use xml::reader::{EventReader, XmlEvent};
|
|
|
|
|
|
|
|
use super::Run;
|
|
|
|
|
|
|
|
use crate::reader::*;
|
|
|
|
use crate::types::BreakType;
|
|
|
|
|
|
|
|
#[derive(PartialEq, Debug)]
|
|
|
|
enum TextState {
|
2020-02-28 04:36:03 +02:00
|
|
|
Idle,
|
2020-02-11 10:01:39 +02:00
|
|
|
Text,
|
|
|
|
Delete,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ElementReader for Run {
|
|
|
|
fn read<R: Read>(
|
|
|
|
r: &mut EventReader<R>,
|
|
|
|
_attrs: &[OwnedAttribute],
|
|
|
|
) -> Result<Self, ReaderError> {
|
|
|
|
let mut run = Run::new();
|
2020-02-28 04:36:03 +02:00
|
|
|
let mut text_state = TextState::Idle;
|
2020-02-11 10:01:39 +02:00
|
|
|
loop {
|
|
|
|
let e = r.next();
|
|
|
|
match e {
|
|
|
|
Ok(XmlEvent::StartElement {
|
|
|
|
attributes, name, ..
|
|
|
|
}) => {
|
2020-12-14 04:42:07 +02:00
|
|
|
match name.prefix.as_deref() {
|
2020-04-07 04:24:56 +03:00
|
|
|
Some("w") => {
|
|
|
|
let e = XMLElement::from_str(&name.local_name).unwrap();
|
2020-07-09 07:25:01 +03:00
|
|
|
|
|
|
|
ignore::ignore_element(e.clone(), XMLElement::RunPropertyChange, r);
|
|
|
|
|
2020-04-07 04:24:56 +03:00
|
|
|
match e {
|
|
|
|
XMLElement::Tab => {
|
|
|
|
run = run.add_tab();
|
|
|
|
}
|
2021-03-24 15:49:32 +02:00
|
|
|
XMLElement::RunProperty => {
|
|
|
|
let p = RunProperty::read(r, &attributes)?;
|
|
|
|
run = run.set_property(p);
|
2020-04-07 04:24:56 +03:00
|
|
|
}
|
|
|
|
XMLElement::Text => text_state = TextState::Text,
|
|
|
|
XMLElement::DeleteText => text_state = TextState::Delete,
|
|
|
|
XMLElement::Break => {
|
|
|
|
if let Some(a) = &attributes.get(0) {
|
|
|
|
run = run.add_break(BreakType::from_str(&a.value)?)
|
|
|
|
} else {
|
|
|
|
run = run.add_break(BreakType::TextWrapping)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
XMLElement::Drawing => {
|
|
|
|
let drawing = Drawing::read(r, &attributes)?;
|
|
|
|
run = run.add_drawing(drawing);
|
|
|
|
}
|
|
|
|
_ => {}
|
2020-02-28 06:50:12 +02:00
|
|
|
}
|
|
|
|
}
|
2020-04-07 04:24:56 +03:00
|
|
|
Some("mc") => {
|
|
|
|
let e = McXMLElement::from_str(&name.local_name).unwrap();
|
|
|
|
match e {
|
|
|
|
McXMLElement::Fallback => {
|
|
|
|
let _ = McFallback::read(r, &attributes)?;
|
|
|
|
}
|
|
|
|
_ => {}
|
2020-02-28 06:42:28 +02:00
|
|
|
}
|
2020-02-11 10:01:39 +02:00
|
|
|
}
|
|
|
|
_ => {}
|
2020-04-07 04:24:56 +03:00
|
|
|
};
|
2020-02-11 10:01:39 +02:00
|
|
|
}
|
2020-02-28 04:36:03 +02:00
|
|
|
Ok(XmlEvent::Characters(c)) => match text_state {
|
|
|
|
TextState::Delete => {
|
2020-02-11 10:01:39 +02:00
|
|
|
run = run.add_delete_text(c);
|
2020-02-28 04:36:03 +02:00
|
|
|
}
|
|
|
|
TextState::Text => {
|
2020-02-11 10:01:39 +02:00
|
|
|
run = run.add_text(c);
|
|
|
|
}
|
2020-02-28 04:36:03 +02:00
|
|
|
_ => {}
|
|
|
|
},
|
|
|
|
Ok(XmlEvent::Whitespace(c)) => match text_state {
|
|
|
|
TextState::Delete => {
|
|
|
|
run = run.add_delete_text(c);
|
|
|
|
}
|
|
|
|
TextState::Text => {
|
|
|
|
run = run.add_text(c);
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
},
|
2020-02-11 10:01:39 +02:00
|
|
|
Ok(XmlEvent::EndElement { name, .. }) => {
|
|
|
|
let e = XMLElement::from_str(&name.local_name).unwrap();
|
2020-02-28 04:36:03 +02:00
|
|
|
match e {
|
|
|
|
XMLElement::Run => {
|
|
|
|
return Ok(run);
|
|
|
|
}
|
|
|
|
XMLElement::DeleteText | XMLElement::Text => text_state = TextState::Idle,
|
|
|
|
_ => {}
|
2020-02-11 10:01:39 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
Err(_) => return Err(ReaderError::XMLReadError),
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
|
|
|
|
use super::*;
|
|
|
|
#[cfg(test)]
|
|
|
|
use pretty_assertions::assert_eq;
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_size_color() {
|
|
|
|
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
|
|
<w:r><w:rPr><w:color w:val="C9211E"/><w:sz w:val="30"/><w:szCs w:val="30"/></w:rPr><w:t>H</w:t></w:r>
|
|
|
|
</w:document>"#;
|
|
|
|
let mut parser = EventReader::new(c.as_bytes());
|
|
|
|
let run = Run::read(&mut parser, &[]).unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
run,
|
|
|
|
Run {
|
|
|
|
children: vec![RunChild::Text(Text::new("H"))],
|
|
|
|
run_property: RunProperty {
|
|
|
|
sz: Some(Sz::new(30)),
|
|
|
|
sz_cs: Some(SzCs::new(30)),
|
|
|
|
color: Some(Color::new("C9211E")),
|
2020-06-08 07:41:13 +03:00
|
|
|
..RunProperty::default()
|
2020-02-11 10:01:39 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_tab() {
|
2020-02-28 06:42:28 +02:00
|
|
|
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
2020-02-11 10:01:39 +02:00
|
|
|
<w:r><w:tab /></w:r>
|
|
|
|
</w:document>"#;
|
|
|
|
let mut parser = EventReader::new(c.as_bytes());
|
|
|
|
let run = Run::read(&mut parser, &[]).unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
run,
|
|
|
|
Run {
|
|
|
|
children: vec![RunChild::Tab(Tab::new())],
|
2020-06-08 07:41:13 +03:00
|
|
|
run_property: RunProperty::default(),
|
2020-02-11 10:01:39 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_br() {
|
2020-02-28 06:42:28 +02:00
|
|
|
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
2020-02-11 10:01:39 +02:00
|
|
|
<w:r><w:br w:type="page" /></w:r>
|
|
|
|
</w:document>"#;
|
|
|
|
let mut parser = EventReader::new(c.as_bytes());
|
|
|
|
let run = Run::read(&mut parser, &[]).unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
run,
|
|
|
|
Run {
|
|
|
|
children: vec![RunChild::Break(Break::new(BreakType::Page))],
|
2020-06-08 07:41:13 +03:00
|
|
|
run_property: RunProperty::default(),
|
2020-02-11 10:01:39 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2020-02-28 06:42:28 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_empty_br() {
|
|
|
|
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
|
|
<w:r><w:br /></w:r>
|
|
|
|
</w:document>"#;
|
|
|
|
let mut parser = EventReader::new(c.as_bytes());
|
|
|
|
let run = Run::read(&mut parser, &[]).unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
run,
|
|
|
|
Run {
|
|
|
|
children: vec![RunChild::Break(Break::new(BreakType::TextWrapping))],
|
2020-06-08 07:41:13 +03:00
|
|
|
run_property: RunProperty::default(),
|
2020-02-28 06:42:28 +02:00
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2020-02-28 08:36:50 +02:00
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_italic_false() {
|
|
|
|
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
|
|
<w:r><w:rPr>
|
|
|
|
<w:b w:val="true"/>
|
|
|
|
<w:i w:val="false"/>
|
|
|
|
</w:rPr></w:r>
|
|
|
|
</w:document>"#;
|
|
|
|
let mut parser = EventReader::new(c.as_bytes());
|
|
|
|
let run = Run::read(&mut parser, &[]).unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
run,
|
|
|
|
Run {
|
|
|
|
children: vec![],
|
|
|
|
run_property: RunProperty {
|
|
|
|
bold: Some(Bold::new()),
|
|
|
|
bold_cs: Some(BoldCs::new()),
|
2021-03-16 10:41:36 +02:00
|
|
|
italic: Some(Italic::new().disable()),
|
|
|
|
italic_cs: Some(ItalicCs::new().disable()),
|
2020-06-08 07:41:13 +03:00
|
|
|
..RunProperty::default()
|
2020-02-28 08:36:50 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
fn test_read_italic_0() {
|
|
|
|
let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
|
|
|
|
<w:r><w:rPr>
|
|
|
|
<w:b w:val="1"/>
|
|
|
|
<w:i w:val="0"/>
|
|
|
|
</w:rPr></w:r>
|
|
|
|
</w:document>"#;
|
|
|
|
let mut parser = EventReader::new(c.as_bytes());
|
|
|
|
let run = Run::read(&mut parser, &[]).unwrap();
|
|
|
|
assert_eq!(
|
|
|
|
run,
|
|
|
|
Run {
|
|
|
|
children: vec![],
|
|
|
|
run_property: RunProperty {
|
|
|
|
bold: Some(Bold::new()),
|
|
|
|
bold_cs: Some(BoldCs::new()),
|
2021-03-16 10:41:36 +02:00
|
|
|
italic: Some(Italic::new().disable()),
|
|
|
|
italic_cs: Some(ItalicCs::new().disable()),
|
2020-06-08 07:41:13 +03:00
|
|
|
..RunProperty::default()
|
2020-02-28 08:36:50 +02:00
|
|
|
},
|
|
|
|
}
|
|
|
|
);
|
|
|
|
}
|
2020-02-11 10:01:39 +02:00
|
|
|
}
|