1use std::{collections::HashMap, str::FromStr};
2
3mod bookmark_id;
4mod build_xml;
5mod comments;
6mod comments_extended;
7mod content_types;
8mod custom_item;
9mod custom_item_property;
10mod custom_item_rels;
11mod doc_props;
12mod document;
13mod document_rels;
14mod elements;
15mod font_table;
16mod footer;
17mod footer_id;
18mod footer_rels;
19mod footnote_id;
20mod footnotes;
21mod header;
22mod header_id;
23mod header_rels;
24mod history_id;
25mod hyperlink_id;
26mod image_collector;
27mod numberings;
28mod paragraph_id;
29mod paragraph_property_change_id;
30mod pic_id;
31mod preset_styles;
32mod rels;
33mod settings;
34mod styles;
35mod taskpanes;
36mod taskpanes_rels;
37mod theme;
38mod toc_key;
39mod web_settings;
40mod webextension;
41mod xml_docx;
42
43pub use build_xml::BuildXML;
44pub(crate) use history_id::HistoryId;
45pub(crate) use hyperlink_id::*;
46pub(crate) use paragraph_id::*;
47pub(crate) use paragraph_property_change_id::ParagraphPropertyChangeId;
48pub(crate) use pic_id::*;
49
50pub use bookmark_id::*;
51pub use comments::*;
52pub use comments_extended::*;
53pub use content_types::*;
54pub use custom_item::*;
55pub use custom_item_property::*;
56pub use custom_item_rels::*;
57pub use doc_props::*;
58pub use document::*;
59pub use document_rels::*;
60pub use elements::*;
61pub use font_table::*;
62pub use footer::*;
63pub use footer_id::*;
64pub use footer_rels::*;
65pub use footnotes::*;
66pub use header::*;
67pub use header_id::*;
68pub use header_rels::*;
69pub use numberings::*;
70pub use rels::*;
71pub use settings::*;
72pub use styles::*;
73pub use taskpanes::*;
74pub use taskpanes_rels::*;
75pub use theme::*;
76pub use toc_key::*;
77pub use web_settings::*;
78pub use webextension::*;
79pub use xml_docx::*;
80
81use base64::Engine;
82use serde::{ser, Serialize};
83
84use self::image_collector::{collect_images_from_paragraph, collect_images_from_table};
85
86#[derive(Debug, Clone)]
87pub struct Image(pub Vec<u8>);
88
89#[derive(Debug, Clone)]
90pub struct Png(pub Vec<u8>);
91
92pub type ImageIdAndPath = (String, String);
93pub type ImageIdAndBuf = (String, Vec<u8>);
94
95impl ser::Serialize for Image {
96 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
97 where
98 S: ser::Serializer,
99 {
100 let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
101 serializer.collect_str(&base64)
102 }
103}
104
105impl ser::Serialize for Png {
106 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
107 where
108 S: ser::Serializer,
109 {
110 let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
111 serializer.collect_str(&base64)
112 }
113}
114
115#[derive(Debug, Clone, Serialize)]
116#[serde(rename_all = "camelCase")]
117pub struct Docx {
118 pub content_type: ContentTypes,
119 pub rels: Rels,
120 pub document_rels: DocumentRels,
121 pub doc_props: DocProps,
122 pub styles: Styles,
123 pub document: Document,
124 pub comments: Comments,
125 pub numberings: Numberings,
126 pub settings: Settings,
127 pub font_table: FontTable,
128 pub media: Vec<(String, Vec<u8>)>,
129 pub comments_extended: CommentsExtended,
130 pub web_settings: WebSettings,
131 pub taskpanes: Option<Taskpanes>,
132 pub taskpanes_rels: TaskpanesRels,
133 pub web_extensions: Vec<WebExtension>,
134 pub custom_items: Vec<CustomItem>,
135 pub custom_item_props: Vec<CustomItemProperty>,
136 pub custom_item_rels: Vec<CustomItemRels>,
137 pub themes: Vec<Theme>,
139 pub images: Vec<(String, String, Image, Png)>,
141 pub hyperlinks: Vec<(String, String, String)>,
143 pub footnotes: Footnotes,
144}
145
146impl Default for Docx {
147 fn default() -> Self {
148 let content_type = ContentTypes::new().set_default();
149 let rels = Rels::new().set_default();
150 let doc_props = DocProps::new(CorePropsConfig::new());
151 let styles = Styles::new();
152 let document = Document::new();
153 let document_rels = DocumentRels::new();
154 let settings = Settings::new();
155 let font_table = FontTable::new();
156 let comments = Comments::new();
157 let numberings = Numberings::new();
158 let media = vec![];
159 let comments_extended = CommentsExtended::new();
160 let web_settings = WebSettings::new();
161 let footnotes = Footnotes::default();
162
163 Docx {
164 content_type,
165 rels,
166 document_rels,
167 doc_props,
168 styles,
169 document,
170 comments,
171 numberings,
172 settings,
173 font_table,
174 media,
175 comments_extended,
176 web_settings,
177 taskpanes: None,
178 taskpanes_rels: TaskpanesRels::new(),
179 web_extensions: vec![],
180 custom_items: vec![],
181 custom_item_props: vec![],
182 custom_item_rels: vec![],
183 themes: vec![],
184 images: vec![],
185 hyperlinks: vec![],
186 footnotes,
187 }
188 }
189}
190
191impl Docx {
192 pub fn new() -> Docx {
193 Default::default()
194 }
195
196 pub fn document(mut self, d: Document) -> Docx {
197 for child in &self.document.children {
198 match child {
199 DocumentChild::Paragraph(paragraph) => {
200 if paragraph.has_numbering {
201 self.document_rels.has_numberings = true;
202 }
203 }
204 DocumentChild::Table(table) => {
205 if table.has_numbering {
206 self.document_rels.has_numberings = true;
207 }
208 }
209 _ => {}
210 }
211 }
212 self.document = d;
213 self
214 }
215
216 pub fn styles(mut self, s: Styles) -> Self {
217 self.styles = s;
218 self
219 }
220
221 pub fn add_style(mut self, s: Style) -> Self {
222 self.styles = self.styles.add_style(s);
223 self
224 }
225
226 pub fn numberings(mut self, n: Numberings) -> Self {
227 self.numberings = n;
228 self
229 }
230
231 pub fn settings(mut self, s: Settings) -> Self {
232 self.settings = s;
233 self
234 }
235
236 pub(crate) fn web_settings(mut self, s: WebSettings) -> Self {
238 self.web_settings = s;
239 self
240 }
241
242 pub(crate) fn add_image(
244 mut self,
245 id: impl Into<String>,
246 path: impl Into<String>,
247 buf: Vec<u8>,
248 ) -> Self {
249 #[cfg(feature = "image")]
250 if let Ok(dimg) = image::load_from_memory(&buf) {
251 let mut png = std::io::Cursor::new(vec![]);
252 dimg.write_to(&mut png, image::ImageFormat::Png)
254 .expect("Unable to write dynamic image");
255
256 self.images
257 .push((id.into(), path.into(), Image(buf), Png(png.into_inner())));
258 }
259 #[cfg(not(feature = "image"))]
260 if buf.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {
262 self.images
263 .push((id.into(), path.into(), Image(buf.clone()), Png(buf)));
264 }
265 self
266 }
267
268 pub(crate) fn add_hyperlink(
270 mut self,
271 id: impl Into<String>,
272 path: impl Into<String>,
273 r#type: impl Into<String>,
274 ) -> Self {
275 self.hyperlinks
276 .push((id.into(), path.into(), r#type.into()));
277 self
278 }
279
280 pub fn comments(mut self, c: Comments) -> Self {
281 self.comments = c;
282 self
283 }
284
285 pub fn comments_extended(mut self, c: CommentsExtended) -> Self {
286 self.comments_extended = c;
287 self
288 }
289
290 pub fn add_paragraph(mut self, p: Paragraph) -> Docx {
291 if p.has_numbering {
292 self.document_rels.has_numberings = true;
295 }
296 self.document = self.document.add_paragraph(p);
297 self
298 }
299
300 pub fn add_section(mut self, s: Section) -> Docx {
301 if s.has_numbering {
302 self.document_rels.has_numberings = true;
305 }
306
307 let mut new_section = s;
308
309 if let Some(header) = new_section.temp_header {
311 if header.has_numbering {
312 self.document_rels.has_numberings = true;
313 }
314 let count = self.document_rels.header_count + 1;
315 new_section = Section {
316 property: new_section
317 .property
318 .header(header, &create_header_rid(count)),
319 children: new_section.children,
320 has_numbering: new_section.has_numbering,
321 temp_header: None,
322 ..Default::default()
323 };
324 self.document_rels.header_count = count;
325 self.content_type = self.content_type.add_header();
326 }
327
328 if let Some(header) = new_section.temp_first_header {
329 if header.has_numbering {
330 self.document_rels.has_numberings = true;
331 }
332 let count = self.document_rels.header_count + 1;
333 new_section = Section {
334 property: new_section
335 .property
336 .first_header(header, &create_header_rid(count)),
337 children: new_section.children,
338 has_numbering: new_section.has_numbering,
339 temp_first_header: None,
340 ..Default::default()
341 };
342 self.document_rels.header_count = count;
343 self.content_type = self.content_type.add_header();
344 }
345
346 if let Some(header) = new_section.temp_even_header {
347 if header.has_numbering {
348 self.document_rels.has_numberings = true;
349 }
350 let count = self.document_rels.header_count + 1;
351 new_section = Section {
352 property: new_section
353 .property
354 .even_header(header, &create_header_rid(count)),
355 children: new_section.children,
356 has_numbering: new_section.has_numbering,
357 temp_even_header: None,
358 ..Default::default()
359 };
360 self.document_rels.header_count = count;
361 self.content_type = self.content_type.add_header();
362 }
363
364 if let Some(header) = new_section.temp_header {
366 if header.has_numbering {
367 self.document_rels.has_numberings = true;
368 }
369 let count = self.document_rels.header_count + 1;
370 new_section = Section {
371 property: new_section
372 .property
373 .header(header, &create_header_rid(count)),
374 children: new_section.children,
375 has_numbering: new_section.has_numbering,
376 temp_header: None,
377 ..Default::default()
378 };
379 self.document_rels.header_count = count;
380 self.content_type = self.content_type.add_header();
381 }
382
383 if let Some(header) = new_section.temp_first_header {
384 if header.has_numbering {
385 self.document_rels.has_numberings = true;
386 }
387 let count = self.document_rels.header_count + 1;
388 new_section = Section {
389 property: new_section
390 .property
391 .first_header(header, &create_header_rid(count)),
392 children: new_section.children,
393 has_numbering: new_section.has_numbering,
394 temp_first_header: None,
395 ..Default::default()
396 };
397 self.document_rels.header_count = count;
398 self.content_type = self.content_type.add_header();
399 }
400
401 if let Some(header) = new_section.temp_even_header {
402 if header.has_numbering {
403 self.document_rels.has_numberings = true;
404 }
405 let count = self.document_rels.header_count + 1;
406 new_section = Section {
407 property: new_section
408 .property
409 .even_header(header, &create_header_rid(count)),
410 children: new_section.children,
411 has_numbering: new_section.has_numbering,
412 temp_even_header: None,
413 ..Default::default()
414 };
415 self.document_rels.header_count = count;
416 self.content_type = self.content_type.add_header();
417 }
418
419 if let Some(footer) = new_section.temp_footer {
421 if footer.has_numbering {
422 self.document_rels.has_numberings = true;
423 }
424 let count = self.document_rels.footer_count + 1;
425 new_section = Section {
426 property: new_section
427 .property
428 .footer(footer, &create_footer_rid(count)),
429 children: new_section.children,
430 has_numbering: new_section.has_numbering,
431 temp_footer: None,
432 ..Default::default()
433 };
434 self.document_rels.footer_count = count;
435 self.content_type = self.content_type.add_footer();
436 }
437
438 if let Some(footer) = new_section.temp_first_footer {
439 if footer.has_numbering {
440 self.document_rels.has_numberings = true;
441 }
442 let count = self.document_rels.footer_count + 1;
443 new_section = Section {
444 property: new_section
445 .property
446 .first_footer(footer, &create_footer_rid(count)),
447 children: new_section.children,
448 has_numbering: new_section.has_numbering,
449 temp_first_footer: None,
450 ..Default::default()
451 };
452 self.document_rels.footer_count = count;
453 self.content_type = self.content_type.add_footer();
454 }
455
456 if let Some(footer) = new_section.temp_even_footer {
457 if footer.has_numbering {
458 self.document_rels.has_numberings = true;
459 }
460 let count = self.document_rels.footer_count + 1;
461 new_section = Section {
462 property: new_section
463 .property
464 .even_footer(footer, &create_footer_rid(count)),
465 children: new_section.children,
466 has_numbering: new_section.has_numbering,
467 temp_even_footer: None,
468 ..Default::default()
469 };
470 self.document_rels.footer_count = count;
471 self.content_type = self.content_type.add_footer();
472 }
473
474 self.document = self.document.add_section(new_section);
475 self
476 }
477
478 pub fn add_structured_data_tag(mut self, t: StructuredDataTag) -> Docx {
479 if t.has_numbering {
480 self.document_rels.has_numberings = true;
483 }
484 self.document = self.document.add_structured_data_tag(t);
485 self
486 }
487
488 pub fn add_table_of_contents(mut self, t: TableOfContents) -> Docx {
489 self.document = self.document.add_table_of_contents(t);
490 self
491 }
492
493 pub fn add_bookmark_start(mut self, id: usize, name: impl Into<String>) -> Docx {
494 self.document = self.document.add_bookmark_start(id, name);
495 self
496 }
497
498 pub fn add_bookmark_end(mut self, id: usize) -> Docx {
499 self.document = self.document.add_bookmark_end(id);
500 self
501 }
502
503 pub fn add_table(mut self, t: Table) -> Docx {
504 if t.has_numbering {
505 self.document_rels.has_numberings = true;
508 }
509 self.document = self.document.add_table(t);
510 self
511 }
512
513 pub fn header(mut self, header: Header) -> Self {
514 if header.has_numbering {
515 self.document_rels.has_numberings = true;
516 }
517 let count = self.document_rels.header_count + 1;
518 self.document.section_property = self
519 .document
520 .section_property
521 .header(header, &create_header_rid(count));
522 self.document_rels.header_count = count;
523 self.content_type = self.content_type.add_header();
524 self
525 }
526
527 pub fn first_header(mut self, header: Header) -> Self {
528 if header.has_numbering {
529 self.document_rels.has_numberings = true;
530 }
531 let count = self.document_rels.header_count + 1;
532 self.document.section_property = self
533 .document
534 .section_property
535 .first_header(header, &create_header_rid(count));
536 self.document_rels.header_count = count;
537 self.content_type = self.content_type.add_header();
538 self
539 }
540
541 pub fn even_header(mut self, header: Header) -> Self {
542 if header.has_numbering {
543 self.document_rels.has_numberings = true;
544 }
545 let count = self.document_rels.header_count + 1;
546 self.document.section_property = self
547 .document
548 .section_property
549 .even_header(header, &create_header_rid(count));
550 self.document_rels.header_count = count;
551 self.content_type = self.content_type.add_header();
552 self.settings = self.settings.even_and_odd_headers();
553 self
554 }
555
556 pub fn footer(mut self, footer: Footer) -> Self {
557 if footer.has_numbering {
558 self.document_rels.has_numberings = true;
559 }
560 let count = self.document_rels.footer_count + 1;
561 self.document.section_property = self
562 .document
563 .section_property
564 .footer(footer, &create_footer_rid(count));
565 self.document_rels.footer_count = count;
566 self.content_type = self.content_type.add_footer();
567 self
568 }
569
570 pub fn first_footer(mut self, footer: Footer) -> Self {
571 if footer.has_numbering {
572 self.document_rels.has_numberings = true;
573 }
574 let count = self.document_rels.footer_count + 1;
575 self.document.section_property = self
576 .document
577 .section_property
578 .first_footer(footer, &create_footer_rid(count));
579 self.document_rels.footer_count = count;
580 self.content_type = self.content_type.add_footer();
581 self
582 }
583
584 pub fn even_footer(mut self, footer: Footer) -> Self {
585 if footer.has_numbering {
586 self.document_rels.has_numberings = true;
587 }
588 let count = self.document_rels.footer_count + 1;
589 self.document.section_property = self
590 .document
591 .section_property
592 .even_footer(footer, &create_footer_rid(count));
593 self.document_rels.footer_count = count;
594 self.content_type = self.content_type.add_footer();
595 self.settings = self.settings.even_and_odd_headers();
596 self
597 }
598
599 pub fn add_abstract_numbering(mut self, num: AbstractNumbering) -> Docx {
600 self.numberings = self.numberings.add_abstract_numbering(num);
601 self
602 }
603
604 pub fn add_numbering(mut self, num: Numbering) -> Docx {
605 self.numberings = self.numberings.add_numbering(num);
606 self
607 }
608
609 pub fn created_at(mut self, date: &str) -> Self {
610 self.doc_props = self.doc_props.created_at(date);
611 self
612 }
613
614 pub fn updated_at(mut self, date: &str) -> Self {
615 self.doc_props = self.doc_props.updated_at(date);
616 self
617 }
618
619 pub fn custom_property(mut self, name: impl Into<String>, item: impl Into<String>) -> Self {
620 self.doc_props = self.doc_props.custom_property(name, item);
621 self
622 }
623
624 pub fn doc_id(mut self, id: &str) -> Self {
625 self.settings = self.settings.doc_id(id);
626 self
627 }
628
629 pub fn default_tab_stop(mut self, stop: usize) -> Self {
630 self.settings = self.settings.default_tab_stop(stop);
631 self
632 }
633
634 pub fn add_doc_var(mut self, name: &str, val: &str) -> Self {
635 self.settings = self.settings.add_doc_var(name, val);
636 self
637 }
638
639 pub fn title_pg(mut self) -> Self {
640 self.document = self.document.title_pg();
641 self
642 }
643
644 pub fn page_size(mut self, w: u32, h: u32) -> Self {
645 self.document = self.document.page_size(PageSize::new().size(w, h));
646 self
647 }
648
649 pub fn page_margin(mut self, margin: crate::types::PageMargin) -> Self {
650 self.document = self.document.page_margin(margin);
651 self
652 }
653
654 pub fn page_orient(mut self, o: crate::types::PageOrientationType) -> Self {
655 self.document = self.document.page_orient(o);
656 self
657 }
658
659 pub fn default_size(mut self, size: usize) -> Self {
660 self.styles = self.styles.default_size(size);
661 self
662 }
663
664 pub fn default_spacing(mut self, spacing: i32) -> Self {
665 self.styles = self.styles.default_spacing(spacing);
666 self
667 }
668
669 pub fn default_fonts(mut self, font: RunFonts) -> Self {
670 self.styles = self.styles.default_fonts(font);
671 self
672 }
673
674 pub fn default_line_spacing(mut self, spacing: LineSpacing) -> Self {
675 self.styles = self.styles.default_line_spacing(spacing);
676 self
677 }
678
679 pub fn taskpanes(mut self) -> Self {
680 self.taskpanes = Some(Taskpanes::new());
681 self.rels = self.rels.add_taskpanes_rel();
682 self.content_type = self.content_type.add_taskpanes();
683 self
684 }
685
686 pub fn web_extension(mut self, ext: WebExtension) -> Self {
687 self.web_extensions.push(ext);
688 self.taskpanes_rels = self.taskpanes_rels.add_rel();
689 self.content_type = self.content_type.add_web_extensions();
690 self
691 }
692
693 pub fn add_custom_item(mut self, id: &str, xml: &str) -> Self {
694 let x = CustomItem::from_str(xml).expect("should parse xml string");
695 self.content_type = self.content_type.add_custom_xml();
696 let rel = CustomItemRels::new().add_item();
697 self.custom_item_props.push(CustomItemProperty::new(id));
698 self.document_rels = self.document_rels.add_custom_item();
699 self.custom_item_rels.push(rel);
700 self.custom_items.push(x);
701 self
702 }
703
704 pub fn page_num_type(mut self, p: PageNumType) -> Self {
705 self.document = self.document.page_num_type(p);
706 self
707 }
708
709 pub fn build(mut self) -> XMLDocx {
710 self.reset();
711
712 self.update_dependencies();
713
714 let tocs: Vec<(usize, Box<TableOfContents>)> = self
715 .document
716 .children
717 .iter()
718 .enumerate()
719 .filter_map(|(i, child)| {
720 if let DocumentChild::TableOfContents(toc) = child {
721 Some((i, toc.clone()))
722 } else {
723 None
724 }
725 })
726 .collect();
727
728 let has_toc = !tocs.is_empty();
729
730 for (i, toc) in tocs {
731 if toc.items.is_empty() && toc.auto {
732 let children =
733 update_document_by_toc(self.document.children, &self.styles, *toc, i);
734 self.document.children = children;
735 }
736 }
737
738 let (images, mut images_bufs) = self.images_in_doc();
739 let (header_images, header_images_bufs) = self.images_in_header();
740 let (footer_images, footer_images_bufs) = self.images_in_footer();
741
742 images_bufs.extend(header_images_bufs);
743 images_bufs.extend(footer_images_bufs);
744
745 let mut header_rels = vec![HeaderRels::new(); 3];
746 for (i, images) in header_images.iter().enumerate() {
747 if let Some(h) = header_rels.get_mut(i) {
748 h.set_images(images.to_owned());
749 }
750 }
751 let mut footer_rels = vec![FooterRels::new(); 3];
752 for (i, images) in footer_images.iter().enumerate() {
753 if let Some(f) = footer_rels.get_mut(i) {
754 f.set_images(images.to_owned());
755 }
756 }
757
758 let web_extensions = self.web_extensions.iter().map(|ext| ext.build()).collect();
759 let custom_items = self.custom_items.iter().map(|xml| xml.build()).collect();
760 let custom_item_props = self.custom_item_props.iter().map(|p| p.build()).collect();
761 let custom_item_rels = self
762 .custom_item_rels
763 .iter()
764 .map(|rel| rel.build())
765 .collect();
766
767 self.document_rels.images = images;
768
769 let mut headers: Vec<&(String, Header)> = self.document.section_property.get_headers();
770
771 self.document.children.iter().for_each(|child| {
772 if let DocumentChild::Section(section) = child {
773 for h in section.property.get_headers() {
774 headers.push(h);
775 }
776 }
777 });
778
779 headers.sort_by(|a, b| a.0.cmp(&b.0));
780 let headers = headers.iter().map(|h| h.1.build()).collect();
781
782 let mut footers: Vec<&(String, Footer)> = self.document.section_property.get_footers();
783
784 self.document.children.iter().for_each(|child| {
785 if let DocumentChild::Section(section) = child {
786 for h in section.property.get_footers() {
787 footers.push(h);
788 }
789 }
790 });
791
792 footers.sort_by(|a, b| a.0.cmp(&b.0));
793 let footers = footers.iter().map(|h| h.1.build()).collect();
794
795 if self.collect_footnotes() {
797 self.content_type = self.content_type.add_footnotes();
799 self.document_rels.has_footnotes = true;
800 }
801
802 if has_toc {
803 for i in 1..=9 {
804 if !self
805 .styles
806 .styles
807 .iter()
808 .any(|s| s.name == Name::new(format!("toc {}", i)))
809 {
810 self.styles = self
811 .styles
812 .add_style(crate::documents::preset_styles::toc(i));
813 }
814 }
815 }
816
817 XMLDocx {
818 content_type: self.content_type.build(),
819 rels: self.rels.build(),
820 doc_props: self.doc_props.build(),
821 styles: self.styles.build(),
822 document: self.document.build(),
823 comments: self.comments.build(),
824 document_rels: self.document_rels.build(),
825 header_rels: header_rels.into_iter().map(|r| r.build()).collect(),
826 footer_rels: footer_rels.into_iter().map(|r| r.build()).collect(),
827 settings: self.settings.build(),
828 font_table: self.font_table.build(),
829 numberings: self.numberings.build(),
830 media: images_bufs,
831 headers,
832 footers,
833 comments_extended: self.comments_extended.build(),
834 taskpanes: self.taskpanes.map(|taskpanes| taskpanes.build()),
835 taskpanes_rels: self.taskpanes_rels.build(),
836 web_extensions,
837 custom_items,
838 custom_item_rels,
839 custom_item_props,
840 footnotes: self.footnotes.build(),
841 }
842 }
843
844 pub fn json(&self) -> String {
845 self.reset();
846
847 serde_json::to_string_pretty(&self).unwrap()
848 }
849
850 pub fn json_with_update_comments(&mut self) -> String {
852 self.reset();
853
854 self.update_dependencies();
855 serde_json::to_string_pretty(&self).unwrap()
856 }
857
858 pub fn comments_json(&mut self) -> String {
860 self.reset();
861 self.update_dependencies();
862 serde_json::to_string_pretty(&self.comments).unwrap()
863 }
864
865 fn reset(&self) {
866 crate::reset_para_id();
867 }
868
869 fn insert_comment_to_map(
870 &self,
871 comment_map: &mut HashMap<usize, String>,
872 c: &CommentRangeStart,
873 ) {
874 let comment = c.get_comment();
875 let comment_id = comment.id();
876 for child in comment.children {
877 if let CommentChild::Paragraph(child) = child {
878 let para_id = child.id.clone();
879 comment_map.insert(comment_id, para_id.clone());
880 }
881 }
883 }
884
885 fn update_dependencies(&mut self) {
887 let mut comments: Vec<Comment> = vec![];
888 let mut comments_extended: Vec<CommentExtended> = vec![];
889 let mut comment_map: HashMap<usize, String> = HashMap::new();
890
891 let mut hyperlink_map: HashMap<String, String> = HashMap::new();
892
893 for child in &self.document.children {
894 match child {
895 DocumentChild::Paragraph(paragraph) => {
896 for child in ¶graph.children {
897 if let ParagraphChild::CommentStart(c) = child {
898 self.insert_comment_to_map(&mut comment_map, c);
899 }
900 if let ParagraphChild::Hyperlink(h) = child {
901 if let HyperlinkData::External { rid, path } = h.link.clone() {
902 hyperlink_map.insert(rid, path);
903 };
904 for child in &h.children {
905 if let ParagraphChild::CommentStart(c) = child {
906 self.insert_comment_to_map(&mut comment_map, c);
907 }
908 }
909 }
910 }
911 }
912 DocumentChild::Table(table) => {
913 collect_dependencies_in_table(
914 table,
915 &mut comments,
916 &mut comments_extended,
917 &mut comment_map,
918 &mut hyperlink_map,
919 );
920 }
921 _ => {}
922 }
923 }
924
925 for child in &self.document.children {
926 match child {
927 DocumentChild::Paragraph(paragraph) => {
928 for child in ¶graph.children {
929 if let ParagraphChild::CommentStart(c) = child {
930 push_comment_and_comment_extended(
931 &mut comments,
932 &mut comments_extended,
933 &comment_map,
934 c,
935 );
936 }
937 if let ParagraphChild::Hyperlink(h) = child {
938 if let HyperlinkData::External { rid, path } = h.link.clone() {
939 hyperlink_map.insert(rid, path);
940 };
941 for child in &h.children {
942 if let ParagraphChild::CommentStart(c) = child {
943 push_comment_and_comment_extended(
944 &mut comments,
945 &mut comments_extended,
946 &comment_map,
947 c,
948 );
949 }
950 }
951 }
952 }
953 }
954 DocumentChild::Table(table) => {
955 collect_dependencies_in_table(
956 table,
957 &mut comments,
958 &mut comments_extended,
959 &mut comment_map,
960 &mut hyperlink_map,
961 );
962 }
963 DocumentChild::TableOfContents(toc) => {
964 for child in &toc.before_contents {
966 if let TocContent::Paragraph(paragraph) = child {
967 for child in ¶graph.children {
968 if let ParagraphChild::CommentStart(c) = child {
969 push_comment_and_comment_extended(
970 &mut comments,
971 &mut comments_extended,
972 &comment_map,
973 c,
974 );
975 }
976 if let ParagraphChild::Hyperlink(h) = child {
977 if let HyperlinkData::External { rid, path } = h.link.clone() {
978 hyperlink_map.insert(rid, path);
979 };
980 for child in &h.children {
981 if let ParagraphChild::CommentStart(c) = child {
982 push_comment_and_comment_extended(
983 &mut comments,
984 &mut comments_extended,
985 &comment_map,
986 c,
987 );
988 }
989 }
990 }
991 }
992 }
993 if let TocContent::Table(table) = child {
994 collect_dependencies_in_table(
995 table,
996 &mut comments,
997 &mut comments_extended,
998 &mut comment_map,
999 &mut hyperlink_map,
1000 );
1001 }
1002 }
1003 for child in &toc.after_contents {
1004 if let TocContent::Paragraph(paragraph) = child {
1005 for child in ¶graph.children {
1006 if let ParagraphChild::CommentStart(c) = child {
1007 push_comment_and_comment_extended(
1008 &mut comments,
1009 &mut comments_extended,
1010 &comment_map,
1011 c,
1012 );
1013 }
1014 if let ParagraphChild::Hyperlink(h) = child {
1015 if let HyperlinkData::External { rid, path } = h.link.clone() {
1016 hyperlink_map.insert(rid, path);
1017 };
1018 for child in &h.children {
1019 if let ParagraphChild::CommentStart(c) = child {
1020 push_comment_and_comment_extended(
1021 &mut comments,
1022 &mut comments_extended,
1023 &comment_map,
1024 c,
1025 );
1026 }
1027 }
1028 }
1029 }
1030 }
1031 if let TocContent::Table(table) = child {
1032 collect_dependencies_in_table(
1033 table,
1034 &mut comments,
1035 &mut comments_extended,
1036 &mut comment_map,
1037 &mut hyperlink_map,
1038 );
1039 }
1040 }
1041 }
1042 _ => {}
1043 }
1044 }
1045 if !comments.is_empty() {
1048 self.document_rels.has_comments = true;
1049 }
1050
1051 self.comments_extended
1052 .add_comments_extended(comments_extended);
1053
1054 self.comments.add_comments(comments);
1055
1056 for (id, d) in hyperlink_map {
1057 self.document_rels
1058 .hyperlinks
1059 .push((id, d, "External".to_string())); }
1061 }
1062
1063 pub(crate) fn store_comments(&mut self, comments: &[Comment]) {
1066 for child in &mut self.document.children {
1067 match child {
1068 DocumentChild::Paragraph(paragraph) => {
1069 for child in &mut paragraph.children {
1070 if let ParagraphChild::CommentStart(ref mut c) = child {
1071 let comment_id = c.get_id();
1072 if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1073 let comment = comment.clone();
1074 c.as_mut().comment(comment);
1075 }
1076 }
1077 if let ParagraphChild::Insert(ref mut insert) = child {
1078 for child in &mut insert.children {
1079 if let InsertChild::CommentStart(ref mut c) = child {
1080 let comment_id = c.get_id();
1081 if let Some(comment) =
1082 comments.iter().find(|c| c.id() == comment_id)
1083 {
1084 let comment = comment.clone();
1085 c.as_mut().comment(comment);
1086 }
1087 } else if let InsertChild::Delete(ref mut d) = child {
1088 for child in &mut d.children {
1089 if let DeleteChild::CommentStart(ref mut c) = child {
1090 let comment_id = c.get_id();
1091 if let Some(comment) =
1092 comments.iter().find(|c| c.id() == comment_id)
1093 {
1094 let comment = comment.clone();
1095 c.as_mut().comment(comment);
1096 }
1097 }
1098 }
1099 }
1100 }
1101 }
1102 if let ParagraphChild::Delete(ref mut delete) = child {
1103 for child in &mut delete.children {
1104 if let DeleteChild::CommentStart(ref mut c) = child {
1105 let comment_id = c.get_id();
1106 if let Some(comment) =
1107 comments.iter().find(|c| c.id() == comment_id)
1108 {
1109 let comment = comment.clone();
1110 c.as_mut().comment(comment);
1111 }
1112 }
1113 }
1114 }
1115 }
1116 }
1117 DocumentChild::Table(table) => store_comments_in_table(table, comments),
1118 _ => {}
1119 }
1120 }
1121
1122 if !comments.is_empty() {
1123 self.document_rels.has_comments = true;
1124 }
1125 }
1126
1127 fn images_in_doc(&mut self) -> (Vec<ImageIdAndPath>, Vec<ImageIdAndBuf>) {
1129 let mut images: Vec<(String, String)> = vec![];
1130 let mut image_bufs: Vec<(String, Vec<u8>)> = vec![];
1131
1132 for child in &mut self.document.children {
1133 match child {
1134 DocumentChild::Paragraph(paragraph) => {
1135 collect_images_from_paragraph(paragraph, &mut images, &mut image_bufs, None);
1136 }
1137 DocumentChild::Table(table) => {
1138 collect_images_from_table(table, &mut images, &mut image_bufs, None);
1139 }
1140 _ => {}
1141 }
1142 }
1143 (images, image_bufs)
1144 }
1145
1146 fn images_in_header(&mut self) -> (Vec<Vec<ImageIdAndPath>>, Vec<ImageIdAndBuf>) {
1147 let mut header_images: Vec<Vec<ImageIdAndPath>> = vec![vec![]; 3];
1148 let mut image_bufs: Vec<(String, Vec<u8>)> = vec![];
1149
1150 if let Some((_, header)) = &mut self.document.section_property.header.as_mut() {
1151 let mut images: Vec<ImageIdAndPath> = vec![];
1152 for child in header.children.iter_mut() {
1153 match child {
1154 HeaderChild::Paragraph(paragraph) => {
1155 collect_images_from_paragraph(
1156 paragraph,
1157 &mut images,
1158 &mut image_bufs,
1159 Some("header"),
1160 );
1161 }
1162 HeaderChild::Table(table) => {
1163 collect_images_from_table(
1164 table,
1165 &mut images,
1166 &mut image_bufs,
1167 Some("header"),
1168 );
1169 }
1170 HeaderChild::StructuredDataTag(tag) => {
1171 for child in tag.children.iter_mut() {
1172 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1173 collect_images_from_paragraph(
1174 paragraph,
1175 &mut images,
1176 &mut image_bufs,
1177 Some("header"),
1178 );
1179 }
1180 if let StructuredDataTagChild::Table(table) = child {
1181 collect_images_from_table(
1182 table,
1183 &mut images,
1184 &mut image_bufs,
1185 Some("header"),
1186 );
1187 }
1188 }
1189 }
1190 }
1191 }
1192 header_images[0] = images;
1193 }
1194
1195 if let Some((_, header)) = &mut self.document.section_property.first_header.as_mut() {
1196 let mut images: Vec<ImageIdAndPath> = vec![];
1197 for child in header.children.iter_mut() {
1198 match child {
1199 HeaderChild::Paragraph(paragraph) => {
1200 collect_images_from_paragraph(
1201 paragraph,
1202 &mut images,
1203 &mut image_bufs,
1204 Some("header"),
1205 );
1206 }
1207 HeaderChild::Table(table) => {
1208 collect_images_from_table(
1209 table,
1210 &mut images,
1211 &mut image_bufs,
1212 Some("header"),
1213 );
1214 }
1215 HeaderChild::StructuredDataTag(tag) => {
1216 for child in tag.children.iter_mut() {
1217 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1218 collect_images_from_paragraph(
1219 paragraph,
1220 &mut images,
1221 &mut image_bufs,
1222 Some("header"),
1223 );
1224 }
1225 if let StructuredDataTagChild::Table(table) = child {
1226 collect_images_from_table(
1227 table,
1228 &mut images,
1229 &mut image_bufs,
1230 Some("header"),
1231 );
1232 }
1233 }
1234 }
1235 }
1236 }
1237 header_images[1] = images;
1238 }
1239
1240 if let Some((_, header)) = &mut self.document.section_property.even_header.as_mut() {
1241 let mut images: Vec<ImageIdAndPath> = vec![];
1242 for child in header.children.iter_mut() {
1243 match child {
1244 HeaderChild::Paragraph(paragraph) => {
1245 collect_images_from_paragraph(
1246 paragraph,
1247 &mut images,
1248 &mut image_bufs,
1249 Some("header"),
1250 );
1251 }
1252 HeaderChild::Table(table) => {
1253 collect_images_from_table(
1254 table,
1255 &mut images,
1256 &mut image_bufs,
1257 Some("header"),
1258 );
1259 }
1260 HeaderChild::StructuredDataTag(tag) => {
1261 for child in tag.children.iter_mut() {
1262 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1263 collect_images_from_paragraph(
1264 paragraph,
1265 &mut images,
1266 &mut image_bufs,
1267 Some("header"),
1268 );
1269 }
1270 if let StructuredDataTagChild::Table(table) = child {
1271 collect_images_from_table(
1272 table,
1273 &mut images,
1274 &mut image_bufs,
1275 Some("header"),
1276 );
1277 }
1278 }
1279 }
1280 }
1281 }
1282 header_images[2] = images;
1283 }
1284 (header_images, image_bufs)
1285 }
1286
1287 fn images_in_footer(&mut self) -> (Vec<Vec<ImageIdAndPath>>, Vec<ImageIdAndBuf>) {
1289 let mut footer_images: Vec<Vec<ImageIdAndPath>> = vec![vec![]; 3];
1290 let mut image_bufs: Vec<(String, Vec<u8>)> = vec![];
1291
1292 if let Some((_, footer)) = &mut self.document.section_property.footer.as_mut() {
1293 let mut images: Vec<ImageIdAndPath> = vec![];
1294 for child in footer.children.iter_mut() {
1295 match child {
1296 FooterChild::Paragraph(paragraph) => {
1297 collect_images_from_paragraph(
1298 paragraph,
1299 &mut images,
1300 &mut image_bufs,
1301 Some("footer"),
1302 );
1303 }
1304 FooterChild::Table(table) => {
1305 collect_images_from_table(
1306 table,
1307 &mut images,
1308 &mut image_bufs,
1309 Some("footer"),
1310 );
1311 }
1312 FooterChild::StructuredDataTag(tag) => {
1313 for child in tag.children.iter_mut() {
1314 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1315 collect_images_from_paragraph(
1316 paragraph,
1317 &mut images,
1318 &mut image_bufs,
1319 Some("header"),
1320 );
1321 }
1322 if let StructuredDataTagChild::Table(table) = child {
1323 collect_images_from_table(
1324 table,
1325 &mut images,
1326 &mut image_bufs,
1327 Some("header"),
1328 );
1329 }
1330 }
1331 }
1332 }
1333 }
1334 footer_images[0] = images;
1335 }
1336
1337 if let Some((_, footer)) = &mut self.document.section_property.first_footer.as_mut() {
1338 let mut images: Vec<ImageIdAndPath> = vec![];
1339 for child in footer.children.iter_mut() {
1340 match child {
1341 FooterChild::Paragraph(paragraph) => {
1342 collect_images_from_paragraph(
1343 paragraph,
1344 &mut images,
1345 &mut image_bufs,
1346 Some("footer"),
1347 );
1348 }
1349 FooterChild::Table(table) => {
1350 collect_images_from_table(
1351 table,
1352 &mut images,
1353 &mut image_bufs,
1354 Some("footer"),
1355 );
1356 }
1357 FooterChild::StructuredDataTag(tag) => {
1358 for child in tag.children.iter_mut() {
1359 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1360 collect_images_from_paragraph(
1361 paragraph,
1362 &mut images,
1363 &mut image_bufs,
1364 Some("header"),
1365 );
1366 }
1367 if let StructuredDataTagChild::Table(table) = child {
1368 collect_images_from_table(
1369 table,
1370 &mut images,
1371 &mut image_bufs,
1372 Some("header"),
1373 );
1374 }
1375 }
1376 }
1377 }
1378 }
1379 footer_images[1] = images;
1380 }
1381
1382 if let Some((_, footer)) = &mut self.document.section_property.even_footer.as_mut() {
1383 let mut images: Vec<ImageIdAndPath> = vec![];
1384 for child in footer.children.iter_mut() {
1385 match child {
1386 FooterChild::Paragraph(paragraph) => {
1387 collect_images_from_paragraph(
1388 paragraph,
1389 &mut images,
1390 &mut image_bufs,
1391 Some("footer"),
1392 );
1393 }
1394 FooterChild::Table(table) => {
1395 collect_images_from_table(
1396 table,
1397 &mut images,
1398 &mut image_bufs,
1399 Some("footer"),
1400 );
1401 }
1402 FooterChild::StructuredDataTag(tag) => {
1403 for child in tag.children.iter_mut() {
1404 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1405 collect_images_from_paragraph(
1406 paragraph,
1407 &mut images,
1408 &mut image_bufs,
1409 Some("header"),
1410 );
1411 }
1412 if let StructuredDataTagChild::Table(table) = child {
1413 collect_images_from_table(
1414 table,
1415 &mut images,
1416 &mut image_bufs,
1417 Some("header"),
1418 );
1419 }
1420 }
1421 }
1422 }
1423 }
1424 footer_images[2] = images;
1425 }
1426 (footer_images, image_bufs)
1427 }
1428
1429 pub fn collect_footnotes(&mut self) -> bool {
1431 let footnotes: Vec<Footnote> = self
1432 .document
1433 .children
1434 .iter()
1435 .filter_map(|child| match child {
1436 DocumentChild::Paragraph(paragraph) => Some(¶graph.children),
1437 _ => None,
1438 })
1439 .flat_map(|children| children.iter())
1440 .filter_map(|para_child| match para_child {
1441 ParagraphChild::Run(run) => Some(&run.children),
1442 _ => None,
1443 })
1444 .flat_map(|children| children.iter())
1445 .filter_map(|run_child| match run_child {
1446 RunChild::FootnoteReference(footnote_ref) => Some(footnote_ref),
1447 _ => None,
1448 })
1449 .map(Into::<Footnote>::into)
1450 .collect();
1451 let is_footnotes = !footnotes.is_empty();
1452 self.footnotes.add(footnotes);
1453 is_footnotes
1454 }
1455}
1456
1457fn collect_dependencies_in_paragraph(
1458 paragraph: &Paragraph,
1459 comments: &mut Vec<Comment>,
1460 comments_extended: &mut Vec<CommentExtended>,
1461 comment_map: &mut HashMap<usize, String>,
1462 hyperlink_map: &mut HashMap<String, String>,
1463) {
1464 for child in ¶graph.children {
1465 if let ParagraphChild::CommentStart(c) = child {
1466 push_comment_and_comment_extended(comments, comments_extended, comment_map, c);
1467 }
1468 if let ParagraphChild::Hyperlink(h) = child {
1469 if let HyperlinkData::External { rid, path } = h.link.clone() {
1470 hyperlink_map.insert(rid, path);
1471 };
1472 for child in &h.children {
1473 if let ParagraphChild::CommentStart(c) = child {
1474 push_comment_and_comment_extended(comments, comments_extended, comment_map, c);
1475 }
1476 }
1477 }
1478 }
1479}
1480
1481fn collect_dependencies_in_table(
1482 table: &Table,
1483 comments: &mut Vec<Comment>,
1484 comments_extended: &mut Vec<CommentExtended>,
1485 comment_map: &mut HashMap<usize, String>,
1486 hyperlink_map: &mut HashMap<String, String>,
1487) {
1488 for TableChild::TableRow(row) in &table.rows {
1489 for TableRowChild::TableCell(cell) in &row.cells {
1490 for content in &cell.children {
1491 match content {
1492 TableCellContent::Paragraph(paragraph) => {
1493 collect_dependencies_in_paragraph(
1494 paragraph,
1495 comments,
1496 comments_extended,
1497 comment_map,
1498 hyperlink_map,
1499 );
1500 }
1501 TableCellContent::Table(table) => collect_dependencies_in_table(
1502 table,
1503 comments,
1504 comments_extended,
1505 comment_map,
1506 hyperlink_map,
1507 ),
1508 TableCellContent::StructuredDataTag(tag) => {
1509 for child in &tag.children {
1510 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1511 collect_dependencies_in_paragraph(
1512 paragraph,
1513 comments,
1514 comments_extended,
1515 comment_map,
1516 hyperlink_map,
1517 );
1518 }
1519 if let StructuredDataTagChild::Table(table) = child {
1520 collect_dependencies_in_table(
1521 table,
1522 comments,
1523 comments_extended,
1524 comment_map,
1525 hyperlink_map,
1526 );
1527 }
1528 }
1529 }
1530 TableCellContent::TableOfContents(t) => {
1531 for child in &t.before_contents {
1532 if let TocContent::Paragraph(paragraph) = child {
1533 collect_dependencies_in_paragraph(
1534 paragraph,
1535 comments,
1536 comments_extended,
1537 comment_map,
1538 hyperlink_map,
1539 );
1540 }
1541 if let TocContent::Table(table) = child {
1542 collect_dependencies_in_table(
1543 table,
1544 comments,
1545 comments_extended,
1546 comment_map,
1547 hyperlink_map,
1548 );
1549 }
1550 }
1551
1552 for child in &t.after_contents {
1553 if let TocContent::Paragraph(paragraph) = child {
1554 collect_dependencies_in_paragraph(
1555 paragraph,
1556 comments,
1557 comments_extended,
1558 comment_map,
1559 hyperlink_map,
1560 );
1561 }
1562 if let TocContent::Table(table) = child {
1563 collect_dependencies_in_table(
1564 table,
1565 comments,
1566 comments_extended,
1567 comment_map,
1568 hyperlink_map,
1569 );
1570 }
1571 }
1572 }
1573 }
1574 }
1575 }
1576 }
1577}
1578
1579fn store_comments_in_paragraph(paragraph: &mut Paragraph, comments: &[Comment]) {
1580 for child in &mut paragraph.children {
1581 if let ParagraphChild::CommentStart(ref mut c) = child {
1582 let comment_id = c.get_id();
1583 if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1584 let comment = comment.clone();
1585 c.as_mut().comment(comment);
1586 }
1587 }
1588 if let ParagraphChild::Insert(ref mut insert) = child {
1589 for child in &mut insert.children {
1590 if let InsertChild::CommentStart(ref mut c) = child {
1591 let comment_id = c.get_id();
1592 if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1593 let comment = comment.clone();
1594 c.as_mut().comment(comment);
1595 }
1596 }
1597 }
1598 }
1599 if let ParagraphChild::Delete(ref mut delete) = child {
1600 for child in &mut delete.children {
1601 if let DeleteChild::CommentStart(ref mut c) = child {
1602 let comment_id = c.get_id();
1603 if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1604 let comment = comment.clone();
1605 c.as_mut().comment(comment);
1606 }
1607 }
1608 }
1609 }
1610 }
1611}
1612
1613fn store_comments_in_table(table: &mut Table, comments: &[Comment]) {
1614 for TableChild::TableRow(row) in &mut table.rows {
1615 for TableRowChild::TableCell(cell) in &mut row.cells {
1616 for content in &mut cell.children {
1617 match content {
1618 TableCellContent::Paragraph(paragraph) => {
1619 store_comments_in_paragraph(paragraph, comments)
1620 }
1621 TableCellContent::Table(ref mut table) => {
1622 store_comments_in_table(table, comments);
1623 }
1624 TableCellContent::StructuredDataTag(ref mut tag) => {
1625 for child in &mut tag.children {
1626 if let StructuredDataTagChild::Paragraph(paragraph) = child {
1627 store_comments_in_paragraph(paragraph, comments);
1628 }
1629 if let StructuredDataTagChild::Table(table) = child {
1630 store_comments_in_table(table, comments);
1631 }
1632 }
1633 }
1634 TableCellContent::TableOfContents(ref mut t) => {
1635 for child in &mut t.before_contents {
1636 if let TocContent::Paragraph(paragraph) = child {
1637 store_comments_in_paragraph(paragraph, comments);
1638 }
1639 if let TocContent::Table(table) = child {
1640 store_comments_in_table(table, comments);
1641 }
1642 }
1643
1644 for child in &mut t.after_contents {
1645 if let TocContent::Paragraph(paragraph) = child {
1646 store_comments_in_paragraph(paragraph, comments);
1647 }
1648 if let TocContent::Table(table) = child {
1649 store_comments_in_table(table, comments);
1650 }
1651 }
1652 }
1653 }
1654 }
1655 }
1656 }
1657}
1658
1659fn push_comment_and_comment_extended(
1660 comments: &mut Vec<Comment>,
1661 comments_extended: &mut Vec<CommentExtended>,
1662 comment_map: &HashMap<usize, String>,
1663 c: &CommentRangeStart,
1664) {
1665 let comment = c.get_comment();
1666 for child in comment.children {
1667 if let CommentChild::Paragraph(child) = child {
1668 let para_id = child.id.clone();
1669 comments.push(c.get_comment());
1670 let comment_extended = CommentExtended::new(para_id);
1671 if let Some(parent_comment_id) = comment.parent_comment_id {
1672 if let Some(parent_para_id) = comment_map.get(&parent_comment_id) {
1673 comments_extended
1674 .push(comment_extended.parent_paragraph_id(parent_para_id.clone()));
1675 }
1676 } else {
1677 comments_extended.push(comment_extended);
1678 }
1679 }
1680 }
1682}
1683
1684fn update_document_by_toc(
1685 document_children: Vec<DocumentChild>,
1686 styles: &Styles,
1687 toc: TableOfContents,
1688 toc_index: usize,
1689) -> Vec<DocumentChild> {
1690 let heading_map = styles.create_heading_style_map();
1691 let mut items = vec![];
1692 let mut children = vec![];
1693 let style_map: std::collections::HashMap<String, usize> = toc
1694 .instr
1695 .styles_with_levels
1696 .iter()
1697 .map(|sl| sl.0.clone())
1698 .collect();
1699
1700 if toc.instr.heading_styles_range.is_none() && !toc.instr.styles_with_levels.is_empty() {
1701 return document_children;
1703 }
1704
1705 let (min, max) = toc.instr.heading_styles_range.unwrap_or((0, 9));
1706
1707 for child in document_children.into_iter() {
1708 match child {
1709 DocumentChild::Paragraph(mut paragraph) => {
1710 if let Some(heading_level) = paragraph
1711 .property
1712 .style
1713 .as_ref()
1714 .map(|p| p.val.to_string())
1715 .and_then(|sid| heading_map.get(&sid))
1716 {
1717 if min <= *heading_level && max >= *heading_level {
1718 let toc_key = TocKey::generate();
1719 items.push(
1720 TableOfContentsItem::new()
1721 .text(paragraph.raw_text())
1722 .toc_key(&toc_key)
1723 .level(*heading_level),
1724 );
1725 paragraph =
1726 Box::new(paragraph.wrap_by_bookmark(generate_bookmark_id(), &toc_key));
1727 }
1728
1729 if let Some((_min, _max)) = toc.instr.tc_field_level_range {
1730 }
1732 }
1733
1734 if let Some(level) = paragraph
1736 .property
1737 .style
1738 .as_ref()
1739 .and_then(|s| style_map.get(&s.val))
1740 {
1741 if min <= *level && max >= *level {
1742 let toc_key = TocKey::generate();
1743 items.push(
1744 TableOfContentsItem::new()
1745 .text(paragraph.raw_text())
1746 .toc_key(&toc_key)
1747 .level(*level),
1748 );
1749 paragraph =
1750 Box::new(paragraph.wrap_by_bookmark(generate_bookmark_id(), &toc_key));
1751 }
1752 }
1753
1754 children.push(DocumentChild::Paragraph(paragraph));
1755 }
1756 DocumentChild::Table(ref _table) => {
1757 children.push(child);
1771 }
1772 _ => {
1773 children.push(child);
1774 }
1775 }
1776 }
1777
1778 let mut toc = toc;
1779 toc.items = items;
1780 children[toc_index] = DocumentChild::TableOfContents(Box::new(toc));
1781 children
1782}