Skip to main content

docx_rs/documents/
mod.rs

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    // reader only
138    pub themes: Vec<Theme>,
139    // reader only
140    pub images: Vec<(String, String, Image, Png)>,
141    // reader only
142    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    // reader only
237    pub(crate) fn web_settings(mut self, s: WebSettings) -> Self {
238        self.web_settings = s;
239        self
240    }
241
242    // reader only
243    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            // For now only png supported
253            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        // without 'image' crate we can only test for PNG file signature
261        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    // reader only
269    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            // If this document has numbering, set numberings.xml to document_rels.
293            // This is because numberings.xml without numbering cause an error on word online.
294            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            // If this document has numbering, set numberings.xml to document_rels.
303            // This is because numberings.xml without numbering cause an error on word online.
304            self.document_rels.has_numberings = true;
305        }
306
307        let mut new_section = s;
308
309        // header
310        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        // header
365        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        // footer
420        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            // If this document has numbering, set numberings.xml to document_rels.
481            // This is because numberings.xml without numbering cause an error on word online.
482            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            // If this document has numbering, set numberings.xml to document_rels.
506            // This is because numberings.xml without numbering cause an error on word online.
507            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        // Collect footnotes
796        if self.collect_footnotes() {
797            // Relationship entry for footnotes
798            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    // Internal: for docx-wasm
851    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    // Internal: for docx-wasm
859    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            // TODO: Support table in comment
882        }
883    }
884
885    // Traverse and clone comments from document and add to comments node.
886    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 &paragraph.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 &paragraph.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                    // TODO:refine later
965                    for child in &toc.before_contents {
966                        if let TocContent::Paragraph(paragraph) = child {
967                            for child in &paragraph.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 &paragraph.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 this document has comments, set comments.xml to document_rels.
1046        // This is because comments.xml without comment cause an error on word online.
1047        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())); // Now support external only
1060        }
1061    }
1062
1063    // Traverse and clone comments from document and add to comments node.
1064    // reader only
1065    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    // Traverse and collect images from document.
1128    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    // Traverse and collect images from header.
1288    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    /// Collect footnotes from all Runs to the docx footnotes node.
1430    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(&paragraph.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 &paragraph.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        // TODO: Support table in comment
1681    }
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        // INFO: if \t option set without heading styles ranges, Microsoft word does not show ToC items...
1702        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                        // TODO: check tc field
1731                    }
1732                }
1733
1734                // Support \t option. Collect toc items if style id matched.
1735                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                // TODO:
1758                // for row in &table.rows {
1759                //     for cell in &row.cells {
1760                //         for content in &cell.children {
1761                //             match content {
1762                //                 TableCellContent::Paragraph(paragraph) => {}
1763                //                 TableCellContent::Table(_) => {
1764                //                     // TODO: Support table in table
1765                //                 }
1766                //             }
1767                //         }
1768                //     }
1769                // }
1770                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}