1use derive_more::From;
2use hard_xml::{XmlRead, XmlWrite};
3use std::borrow::Borrow;
4
5use crate::__xml_test_suites;
6use crate::document::{Paragraph, Run, Table, TableCell};
7use crate::formatting::SectionProperty;
8
9use super::SDT;
10
11#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
15#[cfg_attr(test, derive(PartialEq))]
16#[xml(tag = "w:body")]
17pub struct Body<'a> {
18 #[xml(
20 child = "w:p",
21 child = "w:tbl",
22 child = "w:sectPr",
23 child = "w:sdt",
24 child = "w:bookmarkStart",
25 child = "w:bookmarkEnd"
26 )]
27 pub content: Vec<BodyContent<'a>>,
28}
29
30#[derive(Debug, From, XmlRead, XmlWrite, Clone)]
34#[cfg_attr(test, derive(PartialEq))]
35#[allow(clippy::large_enum_variant)]
36pub enum BodyContent<'a> {
37 #[xml(tag = "w:p")]
38 Paragraph(Paragraph<'a>),
39 #[xml(tag = "w:tbl")]
40 Table(Table<'a>),
41 #[xml(tag = "w:sdt")]
42 Sdt(SDT<'a>),
43 #[xml(tag = "w:sectPr")]
44 SectionProperty(SectionProperty<'a>),
45 #[xml(tag = "w:tc")]
46 TableCell(TableCell<'a>),
47 #[xml(tag = "w:r")]
48 Run(Run<'a>),
49 #[xml(tag = "w:bookmarkStart")]
50 BookmarkStart(crate::document::BookmarkStart<'a>),
51 #[xml(tag = "w:bookmarkEnd")]
52 BookmarkEnd(crate::document::BookmarkEnd<'a>),
53}
54
55impl<'a> Body<'a> {
56 pub fn push<T: Into<BodyContent<'a>>>(&mut self, content: T) -> &mut Self {
57 self.content.push(content.into());
58 self
59 }
60
61 pub fn text(&self) -> String {
62 let v: Vec<_> = self
63 .content
64 .iter()
65 .filter_map(|content| match content {
66 BodyContent::Paragraph(para) => Some(para.text()),
67 BodyContent::Table(_) => None,
68 BodyContent::SectionProperty(_) => None,
69 BodyContent::Sdt(sdt) => Some(sdt.text()),
70 BodyContent::TableCell(_) => None,
71 BodyContent::Run(_) => None,
72 BodyContent::BookmarkStart(_) => None,
73 BodyContent::BookmarkEnd(_) => None,
74 })
75 .collect();
76 v.join("\r\n")
77 }
78
79 pub fn replace_text_simple<S>(&mut self, old: S, new: S)
80 where
81 S: AsRef<str>,
82 {
83 let _d = self.replace_text(&[(old, new)]);
84 }
85
86 pub fn replace_text<'b, I, T, S>(&mut self, dic: T) -> crate::DocxResult<()>
87 where
88 S: AsRef<str> + 'b,
89 T: IntoIterator<Item = I> + Copy,
90 I: Borrow<(S, S)>,
91 {
92 for content in self.content.iter_mut() {
93 match content {
94 BodyContent::Paragraph(p) => {
95 p.replace_text(dic)?;
96 }
97 BodyContent::Table(t) => {
98 t.replace_text(dic)?;
99 }
100 BodyContent::SectionProperty(_) => {}
101 BodyContent::Sdt(_) => {}
102 BodyContent::TableCell(_) => {}
103 BodyContent::Run(_) => {}
104 BodyContent::BookmarkStart(_) => {}
105 BodyContent::BookmarkEnd(_) => {}
106 }
107 }
108 Ok(())
109 }
110
111 }
129
130__xml_test_suites!(
131 Body,
132 Body::default(),
133 r#"<w:body/>"#,
134 Body {
135 content: vec![Paragraph::default().into()]
136 },
137 r#"<w:body><w:p/></w:body>"#,
138 Body {
139 content: vec![Table::default().into()]
140 },
141 r#"<w:body><w:tbl><w:tblPr/><w:tblGrid/></w:tbl></w:body>"#,
142);