1use std::io::Read;
2use std::str::FromStr;
3
4use super::*;
5
6use super::attributes::*;
7
8impl ElementReader for Paragraph {
9 fn read<R: Read>(
10 r: &mut EventReader<R>,
11 attrs: &[OwnedAttribute],
12 ) -> Result<Self, ReaderError> {
13 let mut p = Paragraph::new();
14 if let Some(para_id) = read(attrs, "paraId") {
15 p = p.id(para_id);
16 }
17 loop {
18 let e = r.next();
19 match e {
20 Ok(XmlEvent::StartElement {
21 attributes, name, ..
22 }) => {
23 let e = XMLElement::from_str(&name.local_name).unwrap();
24
25 match e {
26 XMLElement::Run => {
27 let run = Run::read(r, &attributes)?;
28 p = p.add_run(run);
29 continue;
30 }
31 XMLElement::Hyperlink => {
32 let link = Hyperlink::read(r, &attributes)?;
33 p = p.add_hyperlink(link);
34 continue;
35 }
36 XMLElement::Insert => {
37 let ins = Insert::read(r, &attributes)?;
38 p = p.add_insert(ins);
39 continue;
40 }
41 XMLElement::Delete => {
42 let del = Delete::read(r, &attributes)?;
43 p = p.add_delete(del);
44 continue;
45 }
46 XMLElement::BookmarkStart => {
47 let s = BookmarkStart::read(r, &attributes)?;
48 p = p.add_bookmark_start(s.id, s.name);
49 continue;
50 }
51 XMLElement::BookmarkEnd => {
52 let e = BookmarkEnd::read(r, &attributes)?;
53 p = p.add_bookmark_end(e.id);
54 continue;
55 }
56 XMLElement::CommentRangeStart => {
57 if let Some(id) = read(&attributes, "id") {
58 if let Ok(id) = usize::from_str(&id) {
59 let comment = Comment::new(id);
60 p = p.add_comment_start(comment);
61 }
62 }
63 continue;
64 }
65 XMLElement::CommentRangeEnd => {
66 if let Some(id) = read(&attributes, "id") {
67 if let Ok(id) = usize::from_str(&id) {
68 p = p.add_comment_end(id);
69 }
70 }
71 continue;
72 }
73 XMLElement::ParagraphProperty => {
75 if let Ok(pr) = ParagraphProperty::read(r, &attributes) {
76 p.has_numbering = pr.numbering_property.is_some();
77 p.property = pr;
78 }
79 continue;
80 }
81 _ => {}
82 }
83 }
84 Ok(XmlEvent::EndElement { name, .. }) => {
85 let e = XMLElement::from_str(&name.local_name).unwrap();
86 if e == XMLElement::Paragraph {
87 return Ok(p);
88 }
89 }
90 Err(_) => return Err(ReaderError::XMLReadError),
91 _ => {}
92 }
93 }
94 }
95}
96
97#[cfg(test)]
98mod tests {
99
100 use super::*;
101 use crate::types::*;
102 #[cfg(test)]
103 use pretty_assertions::assert_eq;
104
105 #[test]
106 fn test_read_indent() {
107 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
108 <w:p>
109 <w:pPr>
110 <w:ind w:left="1470" w:right="1270" w:hanging="0"/>
111 <w:rPr></w:rPr>
112 </w:pPr>
113 <w:r>
114 <w:rPr></w:rPr>
115 <w:t>a</w:t>
116 </w:r>
117 </w:p>
118</w:document>"#;
119 let mut parser = EventReader::new(c.as_bytes());
120 let p = Paragraph::read(&mut parser, &[]).unwrap();
121
122 assert_eq!(
123 p,
124 Paragraph {
125 id: "12345678".to_owned(),
126 children: vec![ParagraphChild::Run(Box::new(Run::new().add_text("a")))],
127 property: ParagraphProperty {
128 run_property: RunProperty::new(),
129 style: None,
130 numbering_property: None,
131 alignment: None,
132 indent: Some(Indent::new(
133 Some(1470),
134 Some(SpecialIndentType::Hanging(0)),
135 Some(1270),
136 None,
137 )),
138 line_spacing: None,
139 ..Default::default()
140 },
141 has_numbering: false,
142 }
143 );
144 }
145
146 #[test]
147 fn test_read_indent_start_chars() {
148 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
149 <w:p>
150 <w:pPr>
151 <w:ind w:startChars="100" />
152 <w:rPr></w:rPr>
153 </w:pPr>
154 <w:r>
155 <w:rPr></w:rPr>
156 <w:t>a</w:t>
157 </w:r>
158 </w:p>
159</w:document>"#;
160 let mut parser = EventReader::new(c.as_bytes());
161 let p = Paragraph::read(&mut parser, &[]).unwrap();
162
163 assert_eq!(
164 p,
165 Paragraph {
166 id: "12345678".to_owned(),
167 children: vec![ParagraphChild::Run(Box::new(Run::new().add_text("a")))],
168 property: ParagraphProperty {
169 run_property: RunProperty::new(),
170 style: None,
171 numbering_property: None,
172 alignment: None,
173 indent: Some(Indent::new(None, None, None, Some(100))),
174 line_spacing: None,
175 ..Default::default()
176 },
177 has_numbering: false,
178 }
179 );
180 }
181
182 #[test]
183 fn test_read_jc() {
184 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
185 <w:p>
186 <w:pPr>
187 <w:jc w:val="left"/>
188 </w:pPr>
189 </w:p>
190</w:document>"#;
191 let mut parser = EventReader::new(c.as_bytes());
192 let p = Paragraph::read(&mut parser, &[]).unwrap();
193
194 assert_eq!(
195 p,
196 Paragraph {
197 id: "12345678".to_owned(),
198 children: vec![],
199 property: ParagraphProperty {
200 run_property: RunProperty::new(),
201 style: None,
202 numbering_property: None,
203 alignment: Some(Justification::new(AlignmentType::Left.to_string())),
204 indent: None,
205 line_spacing: None,
206 ..Default::default()
207 },
208 has_numbering: false,
209 }
210 );
211 }
212
213 #[test]
214 fn test_read_numbering() {
215 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
216 <w:p>
217 <w:pPr>
218 <w:numPr>
219 <w:ilvl w:val="0"/>
220 <w:numId w:val="1"/>
221 </w:numPr>
222 </w:pPr>
223 </w:p>
224</w:document>"#;
225 let mut parser = EventReader::new(c.as_bytes());
226 let p = Paragraph::read(&mut parser, &[]).unwrap();
227 assert_eq!(
228 p,
229 Paragraph {
230 id: "12345678".to_owned(),
231 children: vec![],
232 property: ParagraphProperty {
233 run_property: RunProperty::new(),
234 style: None,
235 numbering_property: Some(
236 NumberingProperty::new().add_num(NumberingId::new(1), IndentLevel::new(0),)
237 ),
238 alignment: None,
239 indent: None,
240 line_spacing: None,
241 ..Default::default()
242 },
243 has_numbering: true,
244 }
245 );
246 }
247
248 #[test]
249 fn test_read_insert() {
250 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
251 <w:p>
252 <w:ins w:id="0" w:author="unknown" w:date="2019-11-15T14:19:04Z">
253 <w:r>
254 <w:rPr></w:rPr>
255 <w:t>W</w:t>
256 </w:r>
257 </w:ins>
258 </w:p>
259</w:document>"#;
260 let mut parser = EventReader::new(c.as_bytes());
261 let p = Paragraph::read(&mut parser, &[]).unwrap();
262 assert_eq!(
263 p,
264 Paragraph {
265 id: "12345678".to_owned(),
266 children: vec![ParagraphChild::Insert(
267 Insert::new(Run::new().add_text("W"))
268 .author("unknown")
269 .date("2019-11-15T14:19:04Z")
270 )],
271 property: ParagraphProperty {
272 run_property: RunProperty::new(),
273 style: None,
274 numbering_property: None,
275 alignment: None,
276 indent: None,
277 line_spacing: None,
278 ..Default::default()
279 },
280 has_numbering: false,
281 }
282 );
283 }
284
285 #[test]
286 fn test_read_delete() {
287 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
288 <w:p>
289 <w:del w:id="3" w:author="unknown" w:date="2019-11-15T14:19:04Z">
290 <w:r>
291 <w:rPr></w:rPr>
292 <w:delText xml:space="preserve">Hello </w:delText>
293 </w:r>
294 </w:del>
295 </w:p>
296</w:document>"#;
297 let mut parser = EventReader::new(c.as_bytes());
298 let p = Paragraph::read(&mut parser, &[]).unwrap();
299
300 assert_eq!(
301 p,
302 Paragraph {
303 id: "12345678".to_owned(),
304 children: vec![ParagraphChild::Delete(
305 Delete::new()
306 .add_run(Run::new().add_delete_text("Hello "))
307 .author("unknown")
308 .date("2019-11-15T14:19:04Z")
309 )],
310 property: ParagraphProperty {
311 run_property: RunProperty::new(),
312 style: None,
313 numbering_property: None,
314 alignment: None,
315 indent: None,
316 line_spacing: None,
317 ..Default::default()
318 },
319 has_numbering: false,
320 }
321 );
322 }
323
324 #[test]
325 fn test_read_bookmark() {
326 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
327 <w:p>
328 <w:bookmarkStart w:id="0" w:name="ABCD-1234"/>
329 <w:r>
330 <w:rPr></w:rPr>
331 <w:t>Bookmarked</w:t>
332 </w:r>
333 <w:bookmarkEnd w:id="0"/>
334 </w:p>
335</w:document>"#;
336 let mut parser = EventReader::new(c.as_bytes());
337 let p = Paragraph::read(&mut parser, &[]).unwrap();
338
339 assert_eq!(
340 p,
341 Paragraph {
342 id: "12345678".to_owned(),
343 children: vec![
344 ParagraphChild::BookmarkStart(BookmarkStart::new(0, "ABCD-1234")),
345 ParagraphChild::Run(Box::new(Run::new().add_text("Bookmarked"))),
346 ParagraphChild::BookmarkEnd(BookmarkEnd::new(0)),
347 ],
348 property: ParagraphProperty {
349 run_property: RunProperty::new(),
350 style: None,
351 numbering_property: None,
352 alignment: None,
353 indent: None,
354 line_spacing: None,
355 ..Default::default()
356 },
357 has_numbering: false,
358 }
359 );
360 }
361
362 #[test]
363 fn test_read_two_insert() {
364 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
365 <w:p>
366 <w:ins w:id="0" w:author="unknown" w:date="2019-11-15T14:19:04Z">
367 <w:r>
368 <w:rPr></w:rPr>
369 <w:t>W</w:t>
370 </w:r>
371 </w:ins>
372 <w:ins w:id="0" w:author="unknown" w:date="2019-11-15T14:19:04Z">
373 <w:r>
374 <w:rPr></w:rPr>
375 <w:t>H</w:t>
376 </w:r>
377 </w:ins>
378 </w:p>
379</w:document>"#;
380 let mut parser = EventReader::new(c.as_bytes());
381 let p = Paragraph::read(&mut parser, &[]).unwrap();
382 assert_eq!(
383 p,
384 Paragraph {
385 id: "12345678".to_owned(),
386 children: vec![
387 ParagraphChild::Insert(
388 Insert::new(Run::new().add_text("W"))
389 .author("unknown")
390 .date("2019-11-15T14:19:04Z")
391 ),
392 ParagraphChild::Insert(
393 Insert::new(Run::new().add_text("H"))
394 .author("unknown")
395 .date("2019-11-15T14:19:04Z")
396 )
397 ],
398 property: ParagraphProperty {
399 run_property: RunProperty::new(),
400 style: None,
401 numbering_property: None,
402 alignment: None,
403 indent: None,
404 line_spacing: None,
405 ..Default::default()
406 },
407 has_numbering: false,
408 }
409 );
410 }
411
412 #[test]
413 fn test_read_two_run_in_insert() {
414 let c = r#"<w:document xmlns:w="http://schemas.openxmlformats.org/wordprocessingml/2006/main">
415 <w:p>
416 <w:ins w:id="0" w:author="unknown" w:date="2019-11-15T14:19:04Z">
417 <w:r>
418 <w:rPr></w:rPr>
419 <w:t>W</w:t>
420 </w:r>
421 <w:r>
422 <w:rPr></w:rPr>
423 <w:t>H</w:t>
424 </w:r>
425 </w:ins>
426 </w:p>
427</w:document>"#;
428 let mut parser = EventReader::new(c.as_bytes());
429 let p = Paragraph::read(&mut parser, &[]).unwrap();
430 assert_eq!(
431 p,
432 Paragraph {
433 id: "12345678".to_owned(),
434 children: vec![ParagraphChild::Insert(
435 Insert::new(Run::new().add_text("W"))
436 .author("unknown")
437 .date("2019-11-15T14:19:04Z")
438 .add_run(Run::new().add_text("H")),
439 )],
440 property: ParagraphProperty {
441 run_property: RunProperty::new(),
442 style: None,
443 numbering_property: None,
444 alignment: None,
445 indent: None,
446 line_spacing: None,
447 ..Default::default()
448 },
449 has_numbering: false,
450 }
451 );
452 }
453}