Skip to main content

docx_rs/documents/
mod.rs

1use std::{
2    collections::{HashMap, HashSet},
3    str::FromStr,
4};
5
6mod bookmark_id;
7mod build_xml;
8mod comments;
9mod comments_extended;
10mod content_types;
11mod custom_item;
12mod custom_item_property;
13mod custom_item_rels;
14mod doc_props;
15mod document;
16mod document_rels;
17mod elements;
18mod font_table;
19mod footer;
20mod footer_id;
21mod footer_rels;
22mod footnote_id;
23mod footnotes;
24mod header;
25mod header_id;
26mod header_rels;
27mod history_id;
28mod hyperlink_id;
29mod image_collector;
30mod numberings;
31mod paragraph_id;
32mod paragraph_property_change_id;
33mod pic_id;
34mod preset_styles;
35mod rels;
36mod settings;
37mod styles;
38mod taskpanes;
39mod taskpanes_rels;
40mod theme;
41mod toc_key;
42mod web_settings;
43mod webextension;
44mod xml_docx;
45
46pub use build_xml::BuildXML;
47pub(crate) use history_id::HistoryId;
48pub(crate) use hyperlink_id::*;
49pub(crate) use paragraph_id::*;
50pub(crate) use paragraph_property_change_id::ParagraphPropertyChangeId;
51pub(crate) use pic_id::*;
52
53pub use bookmark_id::*;
54pub use comments::*;
55pub use comments_extended::*;
56pub use content_types::*;
57pub use custom_item::*;
58pub use custom_item_property::*;
59pub use custom_item_rels::*;
60pub use doc_props::*;
61pub use document::*;
62pub use document_rels::*;
63pub use elements::*;
64pub use font_table::*;
65pub use footer::*;
66pub use footer_id::*;
67pub use footer_rels::*;
68pub use footnotes::*;
69pub use header::*;
70pub use header_id::*;
71pub use header_rels::*;
72pub use numberings::*;
73pub use rels::*;
74pub use settings::*;
75pub use styles::*;
76pub use taskpanes::*;
77pub use taskpanes_rels::*;
78pub use theme::*;
79pub use toc_key::*;
80pub use web_settings::*;
81pub use webextension::*;
82pub use xml_docx::*;
83
84use base64::Engine;
85use serde::{ser, Serialize};
86
87use self::image_collector::{collect_images_from_paragraph, collect_images_from_table};
88
89#[derive(Debug, Clone)]
90pub struct Image(pub Vec<u8>);
91
92#[derive(Debug, Clone)]
93pub struct Png(pub Vec<u8>);
94
95pub type ImageIdAndPath = (String, String);
96pub type ImageIdAndBuf = (String, Vec<u8>);
97
98impl ser::Serialize for Image {
99    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
100    where
101        S: ser::Serializer,
102    {
103        let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
104        serializer.collect_str(&base64)
105    }
106}
107
108impl ser::Serialize for Png {
109    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
110    where
111        S: ser::Serializer,
112    {
113        let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
114        serializer.collect_str(&base64)
115    }
116}
117
118#[derive(Debug, Clone, Serialize)]
119#[serde(rename_all = "camelCase")]
120pub struct Docx {
121    pub content_type: ContentTypes,
122    pub rels: Rels,
123    pub document_rels: DocumentRels,
124    pub doc_props: DocProps,
125    pub styles: Styles,
126    pub document: Document,
127    pub comments: Comments,
128    pub numberings: Numberings,
129    pub settings: Settings,
130    pub font_table: FontTable,
131    pub media: Vec<(String, Vec<u8>)>,
132    pub comments_extended: CommentsExtended,
133    pub web_settings: WebSettings,
134    pub taskpanes: Option<Taskpanes>,
135    pub taskpanes_rels: TaskpanesRels,
136    pub web_extensions: Vec<WebExtension>,
137    pub custom_items: Vec<CustomItem>,
138    pub custom_item_props: Vec<CustomItemProperty>,
139    pub custom_item_rels: Vec<CustomItemRels>,
140    // reader only
141    pub themes: Vec<Theme>,
142    // reader only
143    pub images: Vec<(String, String, Image, Png)>,
144    // reader only
145    pub hyperlinks: Vec<(String, String, String)>,
146    pub footnotes: Footnotes,
147}
148
149impl Default for Docx {
150    fn default() -> Self {
151        let content_type = ContentTypes::new().set_default();
152        let rels = Rels::new().set_default();
153        let doc_props = DocProps::new(CorePropsConfig::new());
154        let styles = Styles::new();
155        let document = Document::new();
156        let document_rels = DocumentRels::new();
157        let settings = Settings::new();
158        let font_table = FontTable::new();
159        let comments = Comments::new();
160        let numberings = Numberings::new();
161        let media = vec![];
162        let comments_extended = CommentsExtended::new();
163        let web_settings = WebSettings::new();
164        let footnotes = Footnotes::default();
165
166        Docx {
167            content_type,
168            rels,
169            document_rels,
170            doc_props,
171            styles,
172            document,
173            comments,
174            numberings,
175            settings,
176            font_table,
177            media,
178            comments_extended,
179            web_settings,
180            taskpanes: None,
181            taskpanes_rels: TaskpanesRels::new(),
182            web_extensions: vec![],
183            custom_items: vec![],
184            custom_item_props: vec![],
185            custom_item_rels: vec![],
186            themes: vec![],
187            images: vec![],
188            hyperlinks: vec![],
189            footnotes,
190        }
191    }
192}
193
194impl Docx {
195    pub fn new() -> Docx {
196        Default::default()
197    }
198
199    pub fn document(mut self, d: Document) -> Docx {
200        for child in &self.document.children {
201            match child {
202                DocumentChild::Paragraph(paragraph) => {
203                    if paragraph.has_numbering {
204                        self.document_rels.has_numberings = true;
205                    }
206                }
207                DocumentChild::Table(table) => {
208                    if table.has_numbering {
209                        self.document_rels.has_numberings = true;
210                    }
211                }
212                _ => {}
213            }
214        }
215        self.document = d;
216        self
217    }
218
219    pub fn styles(mut self, s: Styles) -> Self {
220        self.styles = s;
221        self
222    }
223
224    pub fn add_style(mut self, s: Style) -> Self {
225        self.styles = self.styles.add_style(s);
226        self
227    }
228
229    pub fn numberings(mut self, n: Numberings) -> Self {
230        self.numberings = n;
231        self
232    }
233
234    pub fn settings(mut self, s: Settings) -> Self {
235        self.settings = s;
236        self
237    }
238
239    // reader only
240    pub(crate) fn web_settings(mut self, s: WebSettings) -> Self {
241        self.web_settings = s;
242        self
243    }
244
245    // reader only
246    pub(crate) fn add_image(
247        mut self,
248        id: impl Into<String>,
249        path: impl Into<String>,
250        buf: Vec<u8>,
251    ) -> Self {
252        #[cfg(feature = "image")]
253        if let Ok(dimg) = image::load_from_memory(&buf) {
254            let mut png = std::io::Cursor::new(vec![]);
255            // For now only png supported
256            dimg.write_to(&mut png, image::ImageFormat::Png)
257                .expect("Unable to write dynamic image");
258
259            self.images
260                .push((id.into(), path.into(), Image(buf), Png(png.into_inner())));
261        }
262        #[cfg(not(feature = "image"))]
263        // without 'image' crate we can only test for PNG file signature
264        if buf.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {
265            self.images
266                .push((id.into(), path.into(), Image(buf.clone()), Png(buf)));
267        }
268        self
269    }
270
271    // reader only
272    pub(crate) fn add_hyperlink(
273        mut self,
274        id: impl Into<String>,
275        path: impl Into<String>,
276        r#type: impl Into<String>,
277    ) -> Self {
278        self.hyperlinks
279            .push((id.into(), path.into(), r#type.into()));
280        self
281    }
282
283    pub fn comments(mut self, c: Comments) -> Self {
284        self.comments = c;
285        self
286    }
287
288    pub fn comments_extended(mut self, c: CommentsExtended) -> Self {
289        self.comments_extended = c;
290        self
291    }
292
293    pub fn add_paragraph(mut self, p: Paragraph) -> Docx {
294        if p.has_numbering {
295            // If this document has numbering, set numberings.xml to document_rels.
296            // This is because numberings.xml without numbering cause an error on word online.
297            self.document_rels.has_numberings = true;
298        }
299        self.document = self.document.add_paragraph(p);
300        self
301    }
302
303    pub fn add_section(mut self, s: Section) -> Docx {
304        if s.has_numbering {
305            // If this document has numbering, set numberings.xml to document_rels.
306            // This is because numberings.xml without numbering cause an error on word online.
307            self.document_rels.has_numberings = true;
308        }
309
310        let mut new_section = s;
311
312        // header
313        if let Some(header) = new_section.temp_header {
314            if header.has_numbering {
315                self.document_rels.has_numberings = true;
316            }
317            let count = self.document_rels.header_count + 1;
318            new_section = Section {
319                property: new_section
320                    .property
321                    .header(header, &create_header_rid(count)),
322                children: new_section.children,
323                has_numbering: new_section.has_numbering,
324                temp_header: None,
325                ..Default::default()
326            };
327            self.document_rels.header_count = count;
328            self.content_type = self.content_type.add_header();
329        }
330
331        if let Some(header) = new_section.temp_first_header {
332            if header.has_numbering {
333                self.document_rels.has_numberings = true;
334            }
335            let count = self.document_rels.header_count + 1;
336            new_section = Section {
337                property: new_section
338                    .property
339                    .first_header(header, &create_header_rid(count)),
340                children: new_section.children,
341                has_numbering: new_section.has_numbering,
342                temp_first_header: None,
343                ..Default::default()
344            };
345            self.document_rels.header_count = count;
346            self.content_type = self.content_type.add_header();
347        }
348
349        if let Some(header) = new_section.temp_even_header {
350            if header.has_numbering {
351                self.document_rels.has_numberings = true;
352            }
353            let count = self.document_rels.header_count + 1;
354            new_section = Section {
355                property: new_section
356                    .property
357                    .even_header(header, &create_header_rid(count)),
358                children: new_section.children,
359                has_numbering: new_section.has_numbering,
360                temp_even_header: None,
361                ..Default::default()
362            };
363            self.document_rels.header_count = count;
364            self.content_type = self.content_type.add_header();
365        }
366
367        // header
368        if let Some(header) = new_section.temp_header {
369            if header.has_numbering {
370                self.document_rels.has_numberings = true;
371            }
372            let count = self.document_rels.header_count + 1;
373            new_section = Section {
374                property: new_section
375                    .property
376                    .header(header, &create_header_rid(count)),
377                children: new_section.children,
378                has_numbering: new_section.has_numbering,
379                temp_header: None,
380                ..Default::default()
381            };
382            self.document_rels.header_count = count;
383            self.content_type = self.content_type.add_header();
384        }
385
386        if let Some(header) = new_section.temp_first_header {
387            if header.has_numbering {
388                self.document_rels.has_numberings = true;
389            }
390            let count = self.document_rels.header_count + 1;
391            new_section = Section {
392                property: new_section
393                    .property
394                    .first_header(header, &create_header_rid(count)),
395                children: new_section.children,
396                has_numbering: new_section.has_numbering,
397                temp_first_header: None,
398                ..Default::default()
399            };
400            self.document_rels.header_count = count;
401            self.content_type = self.content_type.add_header();
402        }
403
404        if let Some(header) = new_section.temp_even_header {
405            if header.has_numbering {
406                self.document_rels.has_numberings = true;
407            }
408            let count = self.document_rels.header_count + 1;
409            new_section = Section {
410                property: new_section
411                    .property
412                    .even_header(header, &create_header_rid(count)),
413                children: new_section.children,
414                has_numbering: new_section.has_numbering,
415                temp_even_header: None,
416                ..Default::default()
417            };
418            self.document_rels.header_count = count;
419            self.content_type = self.content_type.add_header();
420        }
421
422        // footer
423        if let Some(footer) = new_section.temp_footer {
424            if footer.has_numbering {
425                self.document_rels.has_numberings = true;
426            }
427            let count = self.document_rels.footer_count + 1;
428            new_section = Section {
429                property: new_section
430                    .property
431                    .footer(footer, &create_footer_rid(count)),
432                children: new_section.children,
433                has_numbering: new_section.has_numbering,
434                temp_footer: None,
435                ..Default::default()
436            };
437            self.document_rels.footer_count = count;
438            self.content_type = self.content_type.add_footer();
439        }
440
441        if let Some(footer) = new_section.temp_first_footer {
442            if footer.has_numbering {
443                self.document_rels.has_numberings = true;
444            }
445            let count = self.document_rels.footer_count + 1;
446            new_section = Section {
447                property: new_section
448                    .property
449                    .first_footer(footer, &create_footer_rid(count)),
450                children: new_section.children,
451                has_numbering: new_section.has_numbering,
452                temp_first_footer: None,
453                ..Default::default()
454            };
455            self.document_rels.footer_count = count;
456            self.content_type = self.content_type.add_footer();
457        }
458
459        if let Some(footer) = new_section.temp_even_footer {
460            if footer.has_numbering {
461                self.document_rels.has_numberings = true;
462            }
463            let count = self.document_rels.footer_count + 1;
464            new_section = Section {
465                property: new_section
466                    .property
467                    .even_footer(footer, &create_footer_rid(count)),
468                children: new_section.children,
469                has_numbering: new_section.has_numbering,
470                temp_even_footer: None,
471                ..Default::default()
472            };
473            self.document_rels.footer_count = count;
474            self.content_type = self.content_type.add_footer();
475        }
476
477        self.document = self.document.add_section(new_section);
478        self
479    }
480
481    pub fn add_structured_data_tag(mut self, t: StructuredDataTag) -> Docx {
482        if t.has_numbering {
483            // If this document has numbering, set numberings.xml to document_rels.
484            // This is because numberings.xml without numbering cause an error on word online.
485            self.document_rels.has_numberings = true;
486        }
487        self.document = self.document.add_structured_data_tag(t);
488        self
489    }
490
491    pub fn add_table_of_contents(mut self, t: TableOfContents) -> Docx {
492        self.document = self.document.add_table_of_contents(t);
493        self
494    }
495
496    pub fn add_bookmark_start(mut self, id: usize, name: impl Into<String>) -> Docx {
497        self.document = self.document.add_bookmark_start(id, name);
498        self
499    }
500
501    pub fn add_bookmark_end(mut self, id: usize) -> Docx {
502        self.document = self.document.add_bookmark_end(id);
503        self
504    }
505
506    pub fn add_table(mut self, t: Table) -> Docx {
507        if t.has_numbering {
508            // If this document has numbering, set numberings.xml to document_rels.
509            // This is because numberings.xml without numbering cause an error on word online.
510            self.document_rels.has_numberings = true;
511        }
512        self.document = self.document.add_table(t);
513        self
514    }
515
516    pub fn header(mut self, header: Header) -> Self {
517        if header.has_numbering {
518            self.document_rels.has_numberings = true;
519        }
520        let count = self.document_rels.header_count + 1;
521        self.document.section_property = self
522            .document
523            .section_property
524            .header(header, &create_header_rid(count));
525        self.document_rels.header_count = count;
526        self.content_type = self.content_type.add_header();
527        self
528    }
529
530    pub fn first_header(mut self, header: Header) -> Self {
531        if header.has_numbering {
532            self.document_rels.has_numberings = true;
533        }
534        let count = self.document_rels.header_count + 1;
535        self.document.section_property = self
536            .document
537            .section_property
538            .first_header(header, &create_header_rid(count));
539        self.document_rels.header_count = count;
540        self.content_type = self.content_type.add_header();
541        self
542    }
543
544    pub fn even_header(mut self, header: Header) -> Self {
545        if header.has_numbering {
546            self.document_rels.has_numberings = true;
547        }
548        let count = self.document_rels.header_count + 1;
549        self.document.section_property = self
550            .document
551            .section_property
552            .even_header(header, &create_header_rid(count));
553        self.document_rels.header_count = count;
554        self.content_type = self.content_type.add_header();
555        self.settings = self.settings.even_and_odd_headers();
556        self
557    }
558
559    pub fn footer(mut self, footer: Footer) -> Self {
560        if footer.has_numbering {
561            self.document_rels.has_numberings = true;
562        }
563        let count = self.document_rels.footer_count + 1;
564        self.document.section_property = self
565            .document
566            .section_property
567            .footer(footer, &create_footer_rid(count));
568        self.document_rels.footer_count = count;
569        self.content_type = self.content_type.add_footer();
570        self
571    }
572
573    pub fn first_footer(mut self, footer: Footer) -> Self {
574        if footer.has_numbering {
575            self.document_rels.has_numberings = true;
576        }
577        let count = self.document_rels.footer_count + 1;
578        self.document.section_property = self
579            .document
580            .section_property
581            .first_footer(footer, &create_footer_rid(count));
582        self.document_rels.footer_count = count;
583        self.content_type = self.content_type.add_footer();
584        self
585    }
586
587    pub fn even_footer(mut self, footer: Footer) -> Self {
588        if footer.has_numbering {
589            self.document_rels.has_numberings = true;
590        }
591        let count = self.document_rels.footer_count + 1;
592        self.document.section_property = self
593            .document
594            .section_property
595            .even_footer(footer, &create_footer_rid(count));
596        self.document_rels.footer_count = count;
597        self.content_type = self.content_type.add_footer();
598        self.settings = self.settings.even_and_odd_headers();
599        self
600    }
601
602    pub fn add_abstract_numbering(mut self, num: AbstractNumbering) -> Docx {
603        self.numberings = self.numberings.add_abstract_numbering(num);
604        self
605    }
606
607    pub fn add_numbering(mut self, num: Numbering) -> Docx {
608        self.numberings = self.numberings.add_numbering(num);
609        self
610    }
611
612    pub fn created_at(mut self, date: &str) -> Self {
613        self.doc_props = self.doc_props.created_at(date);
614        self
615    }
616
617    pub fn updated_at(mut self, date: &str) -> Self {
618        self.doc_props = self.doc_props.updated_at(date);
619        self
620    }
621
622    pub fn custom_property(mut self, name: impl Into<String>, item: impl Into<String>) -> Self {
623        self.doc_props = self.doc_props.custom_property(name, item);
624        self
625    }
626
627    pub fn doc_id(mut self, id: &str) -> Self {
628        self.settings = self.settings.doc_id(id);
629        self
630    }
631
632    pub fn default_tab_stop(mut self, stop: usize) -> Self {
633        self.settings = self.settings.default_tab_stop(stop);
634        self
635    }
636
637    pub fn add_doc_var(mut self, name: &str, val: &str) -> Self {
638        self.settings = self.settings.add_doc_var(name, val);
639        self
640    }
641
642    pub fn title_pg(mut self) -> Self {
643        self.document = self.document.title_pg();
644        self
645    }
646
647    pub fn page_size(mut self, w: u32, h: u32) -> Self {
648        self.document = self.document.page_size(PageSize::new().size(w, h));
649        self
650    }
651
652    pub fn page_margin(mut self, margin: crate::types::PageMargin) -> Self {
653        self.document = self.document.page_margin(margin);
654        self
655    }
656
657    pub fn page_orient(mut self, o: crate::types::PageOrientationType) -> Self {
658        self.document = self.document.page_orient(o);
659        self
660    }
661
662    pub fn default_size(mut self, size: usize) -> Self {
663        self.styles = self.styles.default_size(size);
664        self
665    }
666
667    pub fn default_spacing(mut self, spacing: i32) -> Self {
668        self.styles = self.styles.default_spacing(spacing);
669        self
670    }
671
672    pub fn default_fonts(mut self, font: RunFonts) -> Self {
673        self.styles = self.styles.default_fonts(font);
674        self
675    }
676
677    pub fn default_line_spacing(mut self, spacing: LineSpacing) -> Self {
678        self.styles = self.styles.default_line_spacing(spacing);
679        self
680    }
681
682    pub fn taskpanes(mut self) -> Self {
683        self.taskpanes = Some(Taskpanes::new());
684        self.rels = self.rels.add_taskpanes_rel();
685        self.content_type = self.content_type.add_taskpanes();
686        self
687    }
688
689    pub fn web_extension(mut self, ext: WebExtension) -> Self {
690        self.web_extensions.push(ext);
691        self.taskpanes_rels = self.taskpanes_rels.add_rel();
692        self.content_type = self.content_type.add_web_extensions();
693        self
694    }
695
696    pub fn add_custom_item(mut self, id: &str, xml: &str) -> Self {
697        let x = CustomItem::from_str(xml).expect("should parse xml string");
698        self.content_type = self.content_type.add_custom_xml();
699        let rel = CustomItemRels::new().add_item();
700        self.custom_item_props.push(CustomItemProperty::new(id));
701        self.document_rels = self.document_rels.add_custom_item();
702        self.custom_item_rels.push(rel);
703        self.custom_items.push(x);
704        self
705    }
706
707    pub fn page_num_type(mut self, p: PageNumType) -> Self {
708        self.document = self.document.page_num_type(p);
709        self
710    }
711
712    pub fn build(mut self) -> XMLDocx {
713        self.reset();
714        self.refresh_duplicate_para_ids();
715
716        self.update_dependencies();
717
718        let tocs: Vec<(usize, Box<TableOfContents>)> = self
719            .document
720            .children
721            .iter()
722            .enumerate()
723            .filter_map(|(i, child)| {
724                if let DocumentChild::TableOfContents(toc) = child {
725                    Some((i, toc.clone()))
726                } else {
727                    None
728                }
729            })
730            .collect();
731
732        let has_toc = !tocs.is_empty();
733
734        for (i, toc) in tocs {
735            if toc.items.is_empty() && toc.auto {
736                let children =
737                    update_document_by_toc(self.document.children, &self.styles, *toc, i);
738                self.document.children = children;
739            }
740        }
741
742        let (images, mut images_bufs) = self.images_in_doc();
743        let (header_images, header_images_bufs) = self.images_in_header();
744        let (footer_images, footer_images_bufs) = self.images_in_footer();
745
746        images_bufs.extend(header_images_bufs);
747        images_bufs.extend(footer_images_bufs);
748
749        let mut header_rels = vec![HeaderRels::new(); 3];
750        for (i, images) in header_images.iter().enumerate() {
751            if let Some(h) = header_rels.get_mut(i) {
752                h.set_images(images.to_owned());
753            }
754        }
755        let mut footer_rels = vec![FooterRels::new(); 3];
756        for (i, images) in footer_images.iter().enumerate() {
757            if let Some(f) = footer_rels.get_mut(i) {
758                f.set_images(images.to_owned());
759            }
760        }
761
762        let web_extensions = self.web_extensions.iter().map(|ext| ext.build()).collect();
763        let custom_items = self.custom_items.iter().map(|xml| xml.build()).collect();
764        let custom_item_props = self.custom_item_props.iter().map(|p| p.build()).collect();
765        let custom_item_rels = self
766            .custom_item_rels
767            .iter()
768            .map(|rel| rel.build())
769            .collect();
770
771        self.document_rels.images = images;
772
773        let mut headers: Vec<&(String, Header)> = self.document.section_property.get_headers();
774
775        self.document.children.iter().for_each(|child| {
776            if let DocumentChild::Section(section) = child {
777                for h in section.property.get_headers() {
778                    headers.push(h);
779                }
780            }
781        });
782
783        headers.sort_by(|a, b| a.0.cmp(&b.0));
784        let headers = headers.iter().map(|h| h.1.build()).collect();
785
786        let mut footers: Vec<&(String, Footer)> = self.document.section_property.get_footers();
787
788        self.document.children.iter().for_each(|child| {
789            if let DocumentChild::Section(section) = child {
790                for h in section.property.get_footers() {
791                    footers.push(h);
792                }
793            }
794        });
795
796        footers.sort_by(|a, b| a.0.cmp(&b.0));
797        let footers = footers.iter().map(|h| h.1.build()).collect();
798
799        // Collect footnotes
800        if self.collect_footnotes() {
801            // Relationship entry for footnotes
802            self.content_type = self.content_type.add_footnotes();
803            self.document_rels.has_footnotes = true;
804        }
805
806        if has_toc {
807            for i in 1..=9 {
808                if !self
809                    .styles
810                    .styles
811                    .iter()
812                    .any(|s| s.name == Name::new(format!("toc {}", i)))
813                {
814                    self.styles = self
815                        .styles
816                        .add_style(crate::documents::preset_styles::toc(i));
817                }
818            }
819        }
820
821        XMLDocx {
822            content_type: self.content_type.build(),
823            rels: self.rels.build(),
824            doc_props: self.doc_props.build(),
825            styles: self.styles.build(),
826            document: self.document.build(),
827            comments: self.comments.build(),
828            document_rels: self.document_rels.build(),
829            header_rels: header_rels.into_iter().map(|r| r.build()).collect(),
830            footer_rels: footer_rels.into_iter().map(|r| r.build()).collect(),
831            settings: self.settings.build(),
832            font_table: self.font_table.build(),
833            numberings: self.numberings.build(),
834            media: images_bufs,
835            headers,
836            footers,
837            comments_extended: self.comments_extended.build(),
838            taskpanes: self.taskpanes.map(|taskpanes| taskpanes.build()),
839            taskpanes_rels: self.taskpanes_rels.build(),
840            web_extensions,
841            custom_items,
842            custom_item_rels,
843            custom_item_props,
844            footnotes: self.footnotes.build(),
845        }
846    }
847
848    pub fn json(&self) -> String {
849        self.reset();
850
851        serde_json::to_string_pretty(&self).unwrap()
852    }
853
854    // Internal: for docx-wasm
855    pub fn json_with_update_comments(&mut self) -> String {
856        self.reset();
857
858        self.update_dependencies();
859        serde_json::to_string_pretty(&self).unwrap()
860    }
861
862    // Internal: for docx-wasm
863    pub fn comments_json(&mut self) -> String {
864        self.reset();
865        self.update_dependencies();
866        serde_json::to_string_pretty(&self.comments).unwrap()
867    }
868
869    fn reset(&self) {
870        crate::reset_para_id();
871    }
872
873    fn refresh_duplicate_para_ids(&mut self) {
874        let mut counts: HashMap<String, usize> = HashMap::new();
875        collect_para_ids_in_docx(self, &mut counts);
876
877        let mut used: HashSet<String> = counts.keys().cloned().collect();
878        let mut seen: HashSet<String> = HashSet::new();
879
880        refresh_para_ids_in_docx(self, &counts, &mut used, &mut seen);
881    }
882
883    fn insert_comment_to_map(
884        &self,
885        comment_map: &mut HashMap<usize, String>,
886        c: &CommentRangeStart,
887    ) {
888        let comment = c.get_comment_ref();
889        let comment_id = comment.id();
890        for child in &comment.children {
891            if let CommentChild::Paragraph(child) = child {
892                let para_id = child.id.clone();
893                comment_map.insert(comment_id, para_id);
894            }
895            // TODO: Support table in comment
896        }
897    }
898
899    // Traverse and clone comments from document and add to comments node.
900    fn update_dependencies(&mut self) {
901        let mut comments: Vec<Comment> = vec![];
902        let mut comments_extended: Vec<CommentExtended> = vec![];
903        let mut comment_map: HashMap<usize, String> = HashMap::new();
904
905        let mut hyperlink_map: HashMap<String, String> = HashMap::new();
906
907        for child in &self.document.children {
908            match child {
909                DocumentChild::Paragraph(paragraph) => {
910                    for child in &paragraph.children {
911                        if let ParagraphChild::CommentStart(c) = child {
912                            self.insert_comment_to_map(&mut comment_map, c);
913                        }
914                        if let ParagraphChild::Hyperlink(h) = child {
915                            for child in &h.children {
916                                if let ParagraphChild::CommentStart(c) = child {
917                                    self.insert_comment_to_map(&mut comment_map, c);
918                                }
919                            }
920                        }
921                    }
922                }
923                DocumentChild::Table(table) => {
924                    collect_comment_map_in_table(table, &mut comment_map);
925                }
926                DocumentChild::TableOfContents(toc) => {
927                    for child in &toc.before_contents {
928                        if let TocContent::Paragraph(paragraph) = child {
929                            collect_comment_map_in_paragraph(paragraph, &mut comment_map);
930                        }
931                        if let TocContent::Table(table) = child {
932                            collect_comment_map_in_table(table, &mut comment_map);
933                        }
934                    }
935                    for child in &toc.after_contents {
936                        if let TocContent::Paragraph(paragraph) = child {
937                            collect_comment_map_in_paragraph(paragraph, &mut comment_map);
938                        }
939                        if let TocContent::Table(table) = child {
940                            collect_comment_map_in_table(table, &mut comment_map);
941                        }
942                    }
943                }
944                _ => {}
945            }
946        }
947
948        for child in &self.document.children {
949            match child {
950                DocumentChild::Paragraph(paragraph) => {
951                    for child in &paragraph.children {
952                        if let ParagraphChild::CommentStart(c) = child {
953                            push_comment_and_comment_extended(
954                                &mut comments,
955                                &mut comments_extended,
956                                &comment_map,
957                                c,
958                            );
959                        }
960                        if let ParagraphChild::Hyperlink(h) = child {
961                            if let HyperlinkData::External { rid, path } = &h.link {
962                                hyperlink_map.insert(rid.clone(), path.clone());
963                            };
964                            for child in &h.children {
965                                if let ParagraphChild::CommentStart(c) = child {
966                                    push_comment_and_comment_extended(
967                                        &mut comments,
968                                        &mut comments_extended,
969                                        &comment_map,
970                                        c,
971                                    );
972                                }
973                            }
974                        }
975                    }
976                }
977                DocumentChild::Table(table) => {
978                    collect_dependencies_in_table(
979                        table,
980                        &mut comments,
981                        &mut comments_extended,
982                        &mut comment_map,
983                        &mut hyperlink_map,
984                    );
985                }
986                DocumentChild::TableOfContents(toc) => {
987                    // TODO:refine later
988                    for child in &toc.before_contents {
989                        if let TocContent::Paragraph(paragraph) = child {
990                            for child in &paragraph.children {
991                                if let ParagraphChild::CommentStart(c) = child {
992                                    push_comment_and_comment_extended(
993                                        &mut comments,
994                                        &mut comments_extended,
995                                        &comment_map,
996                                        c,
997                                    );
998                                }
999                                if let ParagraphChild::Hyperlink(h) = child {
1000                                    if let HyperlinkData::External { rid, path } = &h.link {
1001                                        hyperlink_map.insert(rid.clone(), path.clone());
1002                                    };
1003                                    for child in &h.children {
1004                                        if let ParagraphChild::CommentStart(c) = child {
1005                                            push_comment_and_comment_extended(
1006                                                &mut comments,
1007                                                &mut comments_extended,
1008                                                &comment_map,
1009                                                c,
1010                                            );
1011                                        }
1012                                    }
1013                                }
1014                            }
1015                        }
1016                        if let TocContent::Table(table) = child {
1017                            collect_dependencies_in_table(
1018                                table,
1019                                &mut comments,
1020                                &mut comments_extended,
1021                                &mut comment_map,
1022                                &mut hyperlink_map,
1023                            );
1024                        }
1025                    }
1026                    for child in &toc.after_contents {
1027                        if let TocContent::Paragraph(paragraph) = child {
1028                            for child in &paragraph.children {
1029                                if let ParagraphChild::CommentStart(c) = child {
1030                                    push_comment_and_comment_extended(
1031                                        &mut comments,
1032                                        &mut comments_extended,
1033                                        &comment_map,
1034                                        c,
1035                                    );
1036                                }
1037                                if let ParagraphChild::Hyperlink(h) = child {
1038                                    if let HyperlinkData::External { rid, path } = &h.link {
1039                                        hyperlink_map.insert(rid.clone(), path.clone());
1040                                    };
1041                                    for child in &h.children {
1042                                        if let ParagraphChild::CommentStart(c) = child {
1043                                            push_comment_and_comment_extended(
1044                                                &mut comments,
1045                                                &mut comments_extended,
1046                                                &comment_map,
1047                                                c,
1048                                            );
1049                                        }
1050                                    }
1051                                }
1052                            }
1053                        }
1054                        if let TocContent::Table(table) = child {
1055                            collect_dependencies_in_table(
1056                                table,
1057                                &mut comments,
1058                                &mut comments_extended,
1059                                &mut comment_map,
1060                                &mut hyperlink_map,
1061                            );
1062                        }
1063                    }
1064                }
1065                _ => {}
1066            }
1067        }
1068        // If this document has comments, set comments.xml to document_rels.
1069        // This is because comments.xml without comment cause an error on word online.
1070        if !comments.is_empty() {
1071            self.document_rels.has_comments = true;
1072        }
1073
1074        self.comments_extended
1075            .add_comments_extended(comments_extended);
1076
1077        self.comments.add_comments(comments);
1078
1079        for (id, d) in hyperlink_map {
1080            self.document_rels
1081                .hyperlinks
1082                .push((id, d, "External".to_string())); // Now support external only
1083        }
1084    }
1085
1086    // Traverse and clone comments from document and add to comments node.
1087    // reader only
1088    pub(crate) fn store_comments(&mut self, comments: &[Comment]) {
1089        for child in &mut self.document.children {
1090            match child {
1091                DocumentChild::Paragraph(paragraph) => {
1092                    for child in &mut paragraph.children {
1093                        if let ParagraphChild::CommentStart(ref mut c) = child {
1094                            let comment_id = c.get_id();
1095                            if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1096                                let comment = comment.clone();
1097                                c.as_mut().comment(comment);
1098                            }
1099                        }
1100                        if let ParagraphChild::Insert(ref mut insert) = child {
1101                            for child in &mut insert.children {
1102                                if let InsertChild::CommentStart(ref mut c) = child {
1103                                    let comment_id = c.get_id();
1104                                    if let Some(comment) =
1105                                        comments.iter().find(|c| c.id() == comment_id)
1106                                    {
1107                                        let comment = comment.clone();
1108                                        c.as_mut().comment(comment);
1109                                    }
1110                                } else if let InsertChild::Delete(ref mut d) = child {
1111                                    for child in &mut d.children {
1112                                        if let DeleteChild::CommentStart(ref mut c) = child {
1113                                            let comment_id = c.get_id();
1114                                            if let Some(comment) =
1115                                                comments.iter().find(|c| c.id() == comment_id)
1116                                            {
1117                                                let comment = comment.clone();
1118                                                c.as_mut().comment(comment);
1119                                            }
1120                                        }
1121                                    }
1122                                }
1123                            }
1124                        }
1125                        if let ParagraphChild::Delete(ref mut delete) = child {
1126                            for child in &mut delete.children {
1127                                if let DeleteChild::CommentStart(ref mut c) = child {
1128                                    let comment_id = c.get_id();
1129                                    if let Some(comment) =
1130                                        comments.iter().find(|c| c.id() == comment_id)
1131                                    {
1132                                        let comment = comment.clone();
1133                                        c.as_mut().comment(comment);
1134                                    }
1135                                }
1136                            }
1137                        }
1138                    }
1139                }
1140                DocumentChild::Table(table) => store_comments_in_table(table, comments),
1141                _ => {}
1142            }
1143        }
1144
1145        if !comments.is_empty() {
1146            self.document_rels.has_comments = true;
1147        }
1148    }
1149
1150    // Traverse and collect images from document.
1151    fn images_in_doc(&mut self) -> (Vec<ImageIdAndPath>, Vec<ImageIdAndBuf>) {
1152        let mut images: Vec<(String, String)> = vec![];
1153        let mut image_bufs: Vec<(String, Vec<u8>)> = vec![];
1154
1155        for child in &mut self.document.children {
1156            match child {
1157                DocumentChild::Paragraph(paragraph) => {
1158                    collect_images_from_paragraph(paragraph, &mut images, &mut image_bufs, None);
1159                }
1160                DocumentChild::Table(table) => {
1161                    collect_images_from_table(table, &mut images, &mut image_bufs, None);
1162                }
1163                _ => {}
1164            }
1165        }
1166        (images, image_bufs)
1167    }
1168
1169    fn images_in_header(&mut self) -> (Vec<Vec<ImageIdAndPath>>, Vec<ImageIdAndBuf>) {
1170        let mut header_images: Vec<Vec<ImageIdAndPath>> = vec![vec![]; 3];
1171        let mut image_bufs: Vec<(String, Vec<u8>)> = vec![];
1172
1173        if let Some((_, header)) = &mut self.document.section_property.header.as_mut() {
1174            let mut images: Vec<ImageIdAndPath> = vec![];
1175            for child in header.children.iter_mut() {
1176                match child {
1177                    HeaderChild::Paragraph(paragraph) => {
1178                        collect_images_from_paragraph(
1179                            paragraph,
1180                            &mut images,
1181                            &mut image_bufs,
1182                            Some("header"),
1183                        );
1184                    }
1185                    HeaderChild::Table(table) => {
1186                        collect_images_from_table(
1187                            table,
1188                            &mut images,
1189                            &mut image_bufs,
1190                            Some("header"),
1191                        );
1192                    }
1193                    HeaderChild::StructuredDataTag(tag) => {
1194                        for child in tag.children.iter_mut() {
1195                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1196                                collect_images_from_paragraph(
1197                                    paragraph,
1198                                    &mut images,
1199                                    &mut image_bufs,
1200                                    Some("header"),
1201                                );
1202                            }
1203                            if let StructuredDataTagChild::Table(table) = child {
1204                                collect_images_from_table(
1205                                    table,
1206                                    &mut images,
1207                                    &mut image_bufs,
1208                                    Some("header"),
1209                                );
1210                            }
1211                        }
1212                    }
1213                }
1214            }
1215            header_images[0] = images;
1216        }
1217
1218        if let Some((_, header)) = &mut self.document.section_property.first_header.as_mut() {
1219            let mut images: Vec<ImageIdAndPath> = vec![];
1220            for child in header.children.iter_mut() {
1221                match child {
1222                    HeaderChild::Paragraph(paragraph) => {
1223                        collect_images_from_paragraph(
1224                            paragraph,
1225                            &mut images,
1226                            &mut image_bufs,
1227                            Some("header"),
1228                        );
1229                    }
1230                    HeaderChild::Table(table) => {
1231                        collect_images_from_table(
1232                            table,
1233                            &mut images,
1234                            &mut image_bufs,
1235                            Some("header"),
1236                        );
1237                    }
1238                    HeaderChild::StructuredDataTag(tag) => {
1239                        for child in tag.children.iter_mut() {
1240                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1241                                collect_images_from_paragraph(
1242                                    paragraph,
1243                                    &mut images,
1244                                    &mut image_bufs,
1245                                    Some("header"),
1246                                );
1247                            }
1248                            if let StructuredDataTagChild::Table(table) = child {
1249                                collect_images_from_table(
1250                                    table,
1251                                    &mut images,
1252                                    &mut image_bufs,
1253                                    Some("header"),
1254                                );
1255                            }
1256                        }
1257                    }
1258                }
1259            }
1260            header_images[1] = images;
1261        }
1262
1263        if let Some((_, header)) = &mut self.document.section_property.even_header.as_mut() {
1264            let mut images: Vec<ImageIdAndPath> = vec![];
1265            for child in header.children.iter_mut() {
1266                match child {
1267                    HeaderChild::Paragraph(paragraph) => {
1268                        collect_images_from_paragraph(
1269                            paragraph,
1270                            &mut images,
1271                            &mut image_bufs,
1272                            Some("header"),
1273                        );
1274                    }
1275                    HeaderChild::Table(table) => {
1276                        collect_images_from_table(
1277                            table,
1278                            &mut images,
1279                            &mut image_bufs,
1280                            Some("header"),
1281                        );
1282                    }
1283                    HeaderChild::StructuredDataTag(tag) => {
1284                        for child in tag.children.iter_mut() {
1285                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1286                                collect_images_from_paragraph(
1287                                    paragraph,
1288                                    &mut images,
1289                                    &mut image_bufs,
1290                                    Some("header"),
1291                                );
1292                            }
1293                            if let StructuredDataTagChild::Table(table) = child {
1294                                collect_images_from_table(
1295                                    table,
1296                                    &mut images,
1297                                    &mut image_bufs,
1298                                    Some("header"),
1299                                );
1300                            }
1301                        }
1302                    }
1303                }
1304            }
1305            header_images[2] = images;
1306        }
1307        (header_images, image_bufs)
1308    }
1309
1310    // Traverse and collect images from header.
1311    fn images_in_footer(&mut self) -> (Vec<Vec<ImageIdAndPath>>, Vec<ImageIdAndBuf>) {
1312        let mut footer_images: Vec<Vec<ImageIdAndPath>> = vec![vec![]; 3];
1313        let mut image_bufs: Vec<(String, Vec<u8>)> = vec![];
1314
1315        if let Some((_, footer)) = &mut self.document.section_property.footer.as_mut() {
1316            let mut images: Vec<ImageIdAndPath> = vec![];
1317            for child in footer.children.iter_mut() {
1318                match child {
1319                    FooterChild::Paragraph(paragraph) => {
1320                        collect_images_from_paragraph(
1321                            paragraph,
1322                            &mut images,
1323                            &mut image_bufs,
1324                            Some("footer"),
1325                        );
1326                    }
1327                    FooterChild::Table(table) => {
1328                        collect_images_from_table(
1329                            table,
1330                            &mut images,
1331                            &mut image_bufs,
1332                            Some("footer"),
1333                        );
1334                    }
1335                    FooterChild::StructuredDataTag(tag) => {
1336                        for child in tag.children.iter_mut() {
1337                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1338                                collect_images_from_paragraph(
1339                                    paragraph,
1340                                    &mut images,
1341                                    &mut image_bufs,
1342                                    Some("header"),
1343                                );
1344                            }
1345                            if let StructuredDataTagChild::Table(table) = child {
1346                                collect_images_from_table(
1347                                    table,
1348                                    &mut images,
1349                                    &mut image_bufs,
1350                                    Some("header"),
1351                                );
1352                            }
1353                        }
1354                    }
1355                }
1356            }
1357            footer_images[0] = images;
1358        }
1359
1360        if let Some((_, footer)) = &mut self.document.section_property.first_footer.as_mut() {
1361            let mut images: Vec<ImageIdAndPath> = vec![];
1362            for child in footer.children.iter_mut() {
1363                match child {
1364                    FooterChild::Paragraph(paragraph) => {
1365                        collect_images_from_paragraph(
1366                            paragraph,
1367                            &mut images,
1368                            &mut image_bufs,
1369                            Some("footer"),
1370                        );
1371                    }
1372                    FooterChild::Table(table) => {
1373                        collect_images_from_table(
1374                            table,
1375                            &mut images,
1376                            &mut image_bufs,
1377                            Some("footer"),
1378                        );
1379                    }
1380                    FooterChild::StructuredDataTag(tag) => {
1381                        for child in tag.children.iter_mut() {
1382                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1383                                collect_images_from_paragraph(
1384                                    paragraph,
1385                                    &mut images,
1386                                    &mut image_bufs,
1387                                    Some("header"),
1388                                );
1389                            }
1390                            if let StructuredDataTagChild::Table(table) = child {
1391                                collect_images_from_table(
1392                                    table,
1393                                    &mut images,
1394                                    &mut image_bufs,
1395                                    Some("header"),
1396                                );
1397                            }
1398                        }
1399                    }
1400                }
1401            }
1402            footer_images[1] = images;
1403        }
1404
1405        if let Some((_, footer)) = &mut self.document.section_property.even_footer.as_mut() {
1406            let mut images: Vec<ImageIdAndPath> = vec![];
1407            for child in footer.children.iter_mut() {
1408                match child {
1409                    FooterChild::Paragraph(paragraph) => {
1410                        collect_images_from_paragraph(
1411                            paragraph,
1412                            &mut images,
1413                            &mut image_bufs,
1414                            Some("footer"),
1415                        );
1416                    }
1417                    FooterChild::Table(table) => {
1418                        collect_images_from_table(
1419                            table,
1420                            &mut images,
1421                            &mut image_bufs,
1422                            Some("footer"),
1423                        );
1424                    }
1425                    FooterChild::StructuredDataTag(tag) => {
1426                        for child in tag.children.iter_mut() {
1427                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1428                                collect_images_from_paragraph(
1429                                    paragraph,
1430                                    &mut images,
1431                                    &mut image_bufs,
1432                                    Some("header"),
1433                                );
1434                            }
1435                            if let StructuredDataTagChild::Table(table) = child {
1436                                collect_images_from_table(
1437                                    table,
1438                                    &mut images,
1439                                    &mut image_bufs,
1440                                    Some("header"),
1441                                );
1442                            }
1443                        }
1444                    }
1445                }
1446            }
1447            footer_images[2] = images;
1448        }
1449        (footer_images, image_bufs)
1450    }
1451
1452    /// Collect footnotes from all Runs to the docx footnotes node.
1453    pub fn collect_footnotes(&mut self) -> bool {
1454        let footnotes: Vec<Footnote> = self
1455            .document
1456            .children
1457            .iter()
1458            .filter_map(|child| match child {
1459                DocumentChild::Paragraph(paragraph) => Some(&paragraph.children),
1460                _ => None,
1461            })
1462            .flat_map(|children| children.iter())
1463            .filter_map(|para_child| match para_child {
1464                ParagraphChild::Run(run) => Some(&run.children),
1465                _ => None,
1466            })
1467            .flat_map(|children| children.iter())
1468            .filter_map(|run_child| match run_child {
1469                RunChild::FootnoteReference(footnote_ref) => Some(footnote_ref),
1470                _ => None,
1471            })
1472            .map(Into::<Footnote>::into)
1473            .collect();
1474        let is_footnotes = !footnotes.is_empty();
1475        self.footnotes.add(footnotes);
1476        is_footnotes
1477    }
1478}
1479
1480fn collect_dependencies_in_paragraph(
1481    paragraph: &Paragraph,
1482    comments: &mut Vec<Comment>,
1483    comments_extended: &mut Vec<CommentExtended>,
1484    comment_map: &mut HashMap<usize, String>,
1485    hyperlink_map: &mut HashMap<String, String>,
1486) {
1487    for child in &paragraph.children {
1488        if let ParagraphChild::CommentStart(c) = child {
1489            push_comment_and_comment_extended(comments, comments_extended, comment_map, c);
1490        }
1491        if let ParagraphChild::Hyperlink(h) = child {
1492            if let HyperlinkData::External { rid, path } = &h.link {
1493                hyperlink_map.insert(rid.clone(), path.clone());
1494            };
1495            for child in &h.children {
1496                if let ParagraphChild::CommentStart(c) = child {
1497                    push_comment_and_comment_extended(comments, comments_extended, comment_map, c);
1498                }
1499            }
1500        }
1501    }
1502}
1503
1504fn collect_comment_map_in_paragraph(
1505    paragraph: &Paragraph,
1506    comment_map: &mut HashMap<usize, String>,
1507) {
1508    for child in &paragraph.children {
1509        if let ParagraphChild::CommentStart(c) = child {
1510            let comment = c.get_comment_ref();
1511            let comment_id = comment.id();
1512            for child in &comment.children {
1513                if let CommentChild::Paragraph(child) = child {
1514                    comment_map.insert(comment_id, child.id.clone());
1515                }
1516            }
1517        }
1518        if let ParagraphChild::Hyperlink(h) = child {
1519            for child in &h.children {
1520                if let ParagraphChild::CommentStart(c) = child {
1521                    let comment = c.get_comment_ref();
1522                    let comment_id = comment.id();
1523                    for child in &comment.children {
1524                        if let CommentChild::Paragraph(child) = child {
1525                            comment_map.insert(comment_id, child.id.clone());
1526                        }
1527                    }
1528                }
1529            }
1530        }
1531    }
1532}
1533
1534fn collect_comment_map_in_table(table: &Table, comment_map: &mut HashMap<usize, String>) {
1535    for TableChild::TableRow(row) in &table.rows {
1536        for TableRowChild::TableCell(cell) in &row.cells {
1537            for content in &cell.children {
1538                match content {
1539                    TableCellContent::Paragraph(paragraph) => {
1540                        collect_comment_map_in_paragraph(paragraph, comment_map);
1541                    }
1542                    TableCellContent::Table(table) => {
1543                        collect_comment_map_in_table(table, comment_map)
1544                    }
1545                    TableCellContent::StructuredDataTag(tag) => {
1546                        for child in &tag.children {
1547                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1548                                collect_comment_map_in_paragraph(paragraph, comment_map);
1549                            }
1550                            if let StructuredDataTagChild::Table(table) = child {
1551                                collect_comment_map_in_table(table, comment_map);
1552                            }
1553                        }
1554                    }
1555                    TableCellContent::TableOfContents(t) => {
1556                        for child in &t.before_contents {
1557                            if let TocContent::Paragraph(paragraph) = child {
1558                                collect_comment_map_in_paragraph(paragraph, comment_map);
1559                            }
1560                            if let TocContent::Table(table) = child {
1561                                collect_comment_map_in_table(table, comment_map);
1562                            }
1563                        }
1564                        for child in &t.after_contents {
1565                            if let TocContent::Paragraph(paragraph) = child {
1566                                collect_comment_map_in_paragraph(paragraph, comment_map);
1567                            }
1568                            if let TocContent::Table(table) = child {
1569                                collect_comment_map_in_table(table, comment_map);
1570                            }
1571                        }
1572                    }
1573                }
1574            }
1575        }
1576    }
1577}
1578
1579fn collect_dependencies_in_table(
1580    table: &Table,
1581    comments: &mut Vec<Comment>,
1582    comments_extended: &mut Vec<CommentExtended>,
1583    comment_map: &mut HashMap<usize, String>,
1584    hyperlink_map: &mut HashMap<String, String>,
1585) {
1586    for TableChild::TableRow(row) in &table.rows {
1587        for TableRowChild::TableCell(cell) in &row.cells {
1588            for content in &cell.children {
1589                match content {
1590                    TableCellContent::Paragraph(paragraph) => {
1591                        collect_dependencies_in_paragraph(
1592                            paragraph,
1593                            comments,
1594                            comments_extended,
1595                            comment_map,
1596                            hyperlink_map,
1597                        );
1598                    }
1599                    TableCellContent::Table(table) => collect_dependencies_in_table(
1600                        table,
1601                        comments,
1602                        comments_extended,
1603                        comment_map,
1604                        hyperlink_map,
1605                    ),
1606                    TableCellContent::StructuredDataTag(tag) => {
1607                        for child in &tag.children {
1608                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1609                                collect_dependencies_in_paragraph(
1610                                    paragraph,
1611                                    comments,
1612                                    comments_extended,
1613                                    comment_map,
1614                                    hyperlink_map,
1615                                );
1616                            }
1617                            if let StructuredDataTagChild::Table(table) = child {
1618                                collect_dependencies_in_table(
1619                                    table,
1620                                    comments,
1621                                    comments_extended,
1622                                    comment_map,
1623                                    hyperlink_map,
1624                                );
1625                            }
1626                        }
1627                    }
1628                    TableCellContent::TableOfContents(t) => {
1629                        for child in &t.before_contents {
1630                            if let TocContent::Paragraph(paragraph) = child {
1631                                collect_dependencies_in_paragraph(
1632                                    paragraph,
1633                                    comments,
1634                                    comments_extended,
1635                                    comment_map,
1636                                    hyperlink_map,
1637                                );
1638                            }
1639                            if let TocContent::Table(table) = child {
1640                                collect_dependencies_in_table(
1641                                    table,
1642                                    comments,
1643                                    comments_extended,
1644                                    comment_map,
1645                                    hyperlink_map,
1646                                );
1647                            }
1648                        }
1649
1650                        for child in &t.after_contents {
1651                            if let TocContent::Paragraph(paragraph) = child {
1652                                collect_dependencies_in_paragraph(
1653                                    paragraph,
1654                                    comments,
1655                                    comments_extended,
1656                                    comment_map,
1657                                    hyperlink_map,
1658                                );
1659                            }
1660                            if let TocContent::Table(table) = child {
1661                                collect_dependencies_in_table(
1662                                    table,
1663                                    comments,
1664                                    comments_extended,
1665                                    comment_map,
1666                                    hyperlink_map,
1667                                );
1668                            }
1669                        }
1670                    }
1671                }
1672            }
1673        }
1674    }
1675}
1676
1677fn store_comments_in_paragraph(paragraph: &mut Paragraph, comments: &[Comment]) {
1678    for child in &mut paragraph.children {
1679        if let ParagraphChild::CommentStart(ref mut c) = child {
1680            let comment_id = c.get_id();
1681            if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1682                let comment = comment.clone();
1683                c.as_mut().comment(comment);
1684            }
1685        }
1686        if let ParagraphChild::Insert(ref mut insert) = child {
1687            for child in &mut insert.children {
1688                if let InsertChild::CommentStart(ref mut c) = child {
1689                    let comment_id = c.get_id();
1690                    if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1691                        let comment = comment.clone();
1692                        c.as_mut().comment(comment);
1693                    }
1694                }
1695            }
1696        }
1697        if let ParagraphChild::Delete(ref mut delete) = child {
1698            for child in &mut delete.children {
1699                if let DeleteChild::CommentStart(ref mut c) = child {
1700                    let comment_id = c.get_id();
1701                    if let Some(comment) = comments.iter().find(|c| c.id() == comment_id) {
1702                        let comment = comment.clone();
1703                        c.as_mut().comment(comment);
1704                    }
1705                }
1706            }
1707        }
1708    }
1709}
1710
1711fn store_comments_in_table(table: &mut Table, comments: &[Comment]) {
1712    for TableChild::TableRow(row) in &mut table.rows {
1713        for TableRowChild::TableCell(cell) in &mut row.cells {
1714            for content in &mut cell.children {
1715                match content {
1716                    TableCellContent::Paragraph(paragraph) => {
1717                        store_comments_in_paragraph(paragraph, comments)
1718                    }
1719                    TableCellContent::Table(ref mut table) => {
1720                        store_comments_in_table(table, comments);
1721                    }
1722                    TableCellContent::StructuredDataTag(ref mut tag) => {
1723                        for child in &mut tag.children {
1724                            if let StructuredDataTagChild::Paragraph(paragraph) = child {
1725                                store_comments_in_paragraph(paragraph, comments);
1726                            }
1727                            if let StructuredDataTagChild::Table(table) = child {
1728                                store_comments_in_table(table, comments);
1729                            }
1730                        }
1731                    }
1732                    TableCellContent::TableOfContents(ref mut t) => {
1733                        for child in &mut t.before_contents {
1734                            if let TocContent::Paragraph(paragraph) = child {
1735                                store_comments_in_paragraph(paragraph, comments);
1736                            }
1737                            if let TocContent::Table(table) = child {
1738                                store_comments_in_table(table, comments);
1739                            }
1740                        }
1741
1742                        for child in &mut t.after_contents {
1743                            if let TocContent::Paragraph(paragraph) = child {
1744                                store_comments_in_paragraph(paragraph, comments);
1745                            }
1746                            if let TocContent::Table(table) = child {
1747                                store_comments_in_table(table, comments);
1748                            }
1749                        }
1750                    }
1751                }
1752            }
1753        }
1754    }
1755}
1756
1757fn collect_para_ids_in_docx(docx: &Docx, counts: &mut HashMap<String, usize>) {
1758    for child in &docx.document.children {
1759        collect_para_ids_in_document_child(child, counts);
1760    }
1761    collect_para_ids_in_section_property(&docx.document.section_property, counts);
1762
1763    for comment in &docx.comments.comments {
1764        collect_para_ids_in_comment(comment, counts);
1765    }
1766
1767    for footnote in &docx.footnotes.footnotes {
1768        for paragraph in &footnote.content {
1769            collect_para_ids_in_paragraph(paragraph, counts);
1770        }
1771    }
1772}
1773
1774fn collect_para_ids_in_document_child(child: &DocumentChild, counts: &mut HashMap<String, usize>) {
1775    match child {
1776        DocumentChild::Paragraph(paragraph) => collect_para_ids_in_paragraph(paragraph, counts),
1777        DocumentChild::Table(table) => collect_para_ids_in_table(table, counts),
1778        DocumentChild::StructuredDataTag(tag) => {
1779            collect_para_ids_in_structured_data_tag(tag, counts)
1780        }
1781        DocumentChild::TableOfContents(toc) => collect_para_ids_in_toc(toc, counts),
1782        DocumentChild::Section(section) => collect_para_ids_in_section(section, counts),
1783        _ => {}
1784    }
1785}
1786
1787fn collect_para_ids_in_section(section: &Section, counts: &mut HashMap<String, usize>) {
1788    for child in &section.children {
1789        match child {
1790            SectionChild::Paragraph(paragraph) => collect_para_ids_in_paragraph(paragraph, counts),
1791            SectionChild::Table(table) => collect_para_ids_in_table(table, counts),
1792            SectionChild::StructuredDataTag(tag) => {
1793                collect_para_ids_in_structured_data_tag(tag, counts)
1794            }
1795            SectionChild::TableOfContents(toc) => collect_para_ids_in_toc(toc, counts),
1796            _ => {}
1797        }
1798    }
1799    collect_para_ids_in_section_property(&section.property, counts);
1800}
1801
1802fn collect_para_ids_in_section_property(
1803    property: &SectionProperty,
1804    counts: &mut HashMap<String, usize>,
1805) {
1806    if let Some((_, header)) = property.header.as_ref() {
1807        collect_para_ids_in_header(header, counts);
1808    }
1809    if let Some((_, header)) = property.first_header.as_ref() {
1810        collect_para_ids_in_header(header, counts);
1811    }
1812    if let Some((_, header)) = property.even_header.as_ref() {
1813        collect_para_ids_in_header(header, counts);
1814    }
1815    if let Some((_, footer)) = property.footer.as_ref() {
1816        collect_para_ids_in_footer(footer, counts);
1817    }
1818    if let Some((_, footer)) = property.first_footer.as_ref() {
1819        collect_para_ids_in_footer(footer, counts);
1820    }
1821    if let Some((_, footer)) = property.even_footer.as_ref() {
1822        collect_para_ids_in_footer(footer, counts);
1823    }
1824}
1825
1826fn collect_para_ids_in_header(header: &Header, counts: &mut HashMap<String, usize>) {
1827    for child in &header.children {
1828        match child {
1829            HeaderChild::Paragraph(paragraph) => collect_para_ids_in_paragraph(paragraph, counts),
1830            HeaderChild::Table(table) => collect_para_ids_in_table(table, counts),
1831            HeaderChild::StructuredDataTag(tag) => {
1832                collect_para_ids_in_structured_data_tag(tag, counts)
1833            }
1834        }
1835    }
1836}
1837
1838fn collect_para_ids_in_footer(footer: &Footer, counts: &mut HashMap<String, usize>) {
1839    for child in &footer.children {
1840        match child {
1841            FooterChild::Paragraph(paragraph) => collect_para_ids_in_paragraph(paragraph, counts),
1842            FooterChild::Table(table) => collect_para_ids_in_table(table, counts),
1843            FooterChild::StructuredDataTag(tag) => {
1844                collect_para_ids_in_structured_data_tag(tag, counts)
1845            }
1846        }
1847    }
1848}
1849
1850fn collect_para_ids_in_toc(toc: &TableOfContents, counts: &mut HashMap<String, usize>) {
1851    for child in &toc.before_contents {
1852        match child {
1853            TocContent::Paragraph(paragraph) => collect_para_ids_in_paragraph(paragraph, counts),
1854            TocContent::Table(table) => collect_para_ids_in_table(table, counts),
1855        }
1856    }
1857    for child in &toc.after_contents {
1858        match child {
1859            TocContent::Paragraph(paragraph) => collect_para_ids_in_paragraph(paragraph, counts),
1860            TocContent::Table(table) => collect_para_ids_in_table(table, counts),
1861        }
1862    }
1863}
1864
1865fn collect_para_ids_in_table(table: &Table, counts: &mut HashMap<String, usize>) {
1866    for TableChild::TableRow(row) in &table.rows {
1867        for TableRowChild::TableCell(cell) in &row.cells {
1868            for content in &cell.children {
1869                match content {
1870                    TableCellContent::Paragraph(paragraph) => {
1871                        collect_para_ids_in_paragraph(paragraph, counts)
1872                    }
1873                    TableCellContent::Table(table) => collect_para_ids_in_table(table, counts),
1874                    TableCellContent::StructuredDataTag(tag) => {
1875                        collect_para_ids_in_structured_data_tag(tag, counts)
1876                    }
1877                    TableCellContent::TableOfContents(toc) => collect_para_ids_in_toc(toc, counts),
1878                }
1879            }
1880        }
1881    }
1882}
1883
1884fn collect_para_ids_in_paragraph(paragraph: &Paragraph, counts: &mut HashMap<String, usize>) {
1885    *counts.entry(paragraph.id.clone()).or_insert(0) += 1;
1886
1887    for child in &paragraph.children {
1888        match child {
1889            ParagraphChild::CommentStart(c) => collect_para_ids_in_comment(&c.comment, counts),
1890            ParagraphChild::Insert(insert) => collect_para_ids_in_insert(insert, counts),
1891            ParagraphChild::Delete(delete) => collect_para_ids_in_delete(delete, counts),
1892            ParagraphChild::Hyperlink(hyperlink) => {
1893                collect_para_ids_in_hyperlink(hyperlink, counts)
1894            }
1895            ParagraphChild::StructuredDataTag(tag) => {
1896                collect_para_ids_in_structured_data_tag(tag, counts)
1897            }
1898            _ => {}
1899        }
1900    }
1901}
1902
1903fn collect_para_ids_in_hyperlink(hyperlink: &Hyperlink, counts: &mut HashMap<String, usize>) {
1904    for child in &hyperlink.children {
1905        match child {
1906            ParagraphChild::CommentStart(c) => collect_para_ids_in_comment(&c.comment, counts),
1907            ParagraphChild::Insert(insert) => collect_para_ids_in_insert(insert, counts),
1908            ParagraphChild::Delete(delete) => collect_para_ids_in_delete(delete, counts),
1909            ParagraphChild::StructuredDataTag(tag) => {
1910                collect_para_ids_in_structured_data_tag(tag, counts)
1911            }
1912            _ => {}
1913        }
1914    }
1915}
1916
1917fn collect_para_ids_in_insert(insert: &Insert, counts: &mut HashMap<String, usize>) {
1918    for child in &insert.children {
1919        match child {
1920            InsertChild::CommentStart(c) => collect_para_ids_in_comment(&c.comment, counts),
1921            InsertChild::Delete(delete) => collect_para_ids_in_delete(delete, counts),
1922            _ => {}
1923        }
1924    }
1925}
1926
1927fn collect_para_ids_in_delete(delete: &Delete, counts: &mut HashMap<String, usize>) {
1928    for child in &delete.children {
1929        if let DeleteChild::CommentStart(c) = child {
1930            collect_para_ids_in_comment(&c.comment, counts);
1931        }
1932    }
1933}
1934
1935fn collect_para_ids_in_structured_data_tag(
1936    tag: &StructuredDataTag,
1937    counts: &mut HashMap<String, usize>,
1938) {
1939    for child in &tag.children {
1940        match child {
1941            StructuredDataTagChild::Paragraph(paragraph) => {
1942                collect_para_ids_in_paragraph(paragraph, counts)
1943            }
1944            StructuredDataTagChild::Table(table) => collect_para_ids_in_table(table, counts),
1945            StructuredDataTagChild::CommentStart(c) => {
1946                collect_para_ids_in_comment(&c.comment, counts)
1947            }
1948            StructuredDataTagChild::StructuredDataTag(inner) => {
1949                collect_para_ids_in_structured_data_tag(inner, counts)
1950            }
1951            _ => {}
1952        }
1953    }
1954}
1955
1956fn collect_para_ids_in_comment(comment: &Comment, counts: &mut HashMap<String, usize>) {
1957    for child in &comment.children {
1958        match child {
1959            CommentChild::Paragraph(paragraph) => collect_para_ids_in_paragraph(paragraph, counts),
1960            CommentChild::Table(table) => collect_para_ids_in_table(table, counts),
1961        }
1962    }
1963}
1964
1965fn refresh_para_ids_in_docx(
1966    docx: &mut Docx,
1967    counts: &HashMap<String, usize>,
1968    used: &mut HashSet<String>,
1969    seen: &mut HashSet<String>,
1970) {
1971    for child in &mut docx.document.children {
1972        refresh_para_ids_in_document_child(child, counts, used, seen);
1973    }
1974    refresh_para_ids_in_section_property(&mut docx.document.section_property, counts, used, seen);
1975
1976    for comment in &mut docx.comments.comments {
1977        refresh_para_ids_in_comment(comment, counts, used, seen);
1978    }
1979
1980    for footnote in &mut docx.footnotes.footnotes {
1981        for paragraph in &mut footnote.content {
1982            refresh_para_ids_in_paragraph(paragraph, counts, used, seen);
1983        }
1984    }
1985}
1986
1987fn refresh_para_ids_in_document_child(
1988    child: &mut DocumentChild,
1989    counts: &HashMap<String, usize>,
1990    used: &mut HashSet<String>,
1991    seen: &mut HashSet<String>,
1992) {
1993    match child {
1994        DocumentChild::Paragraph(paragraph) => {
1995            refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
1996        }
1997        DocumentChild::Table(table) => refresh_para_ids_in_table(table, counts, used, seen),
1998        DocumentChild::StructuredDataTag(tag) => {
1999            refresh_para_ids_in_structured_data_tag(tag, counts, used, seen)
2000        }
2001        DocumentChild::TableOfContents(toc) => refresh_para_ids_in_toc(toc, counts, used, seen),
2002        DocumentChild::Section(section) => refresh_para_ids_in_section(section, counts, used, seen),
2003        _ => {}
2004    }
2005}
2006
2007fn refresh_para_ids_in_section(
2008    section: &mut Section,
2009    counts: &HashMap<String, usize>,
2010    used: &mut HashSet<String>,
2011    seen: &mut HashSet<String>,
2012) {
2013    for child in &mut section.children {
2014        match child {
2015            SectionChild::Paragraph(paragraph) => {
2016                refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2017            }
2018            SectionChild::Table(table) => refresh_para_ids_in_table(table, counts, used, seen),
2019            SectionChild::StructuredDataTag(tag) => {
2020                refresh_para_ids_in_structured_data_tag(tag, counts, used, seen)
2021            }
2022            SectionChild::TableOfContents(toc) => refresh_para_ids_in_toc(toc, counts, used, seen),
2023            _ => {}
2024        }
2025    }
2026    refresh_para_ids_in_section_property(&mut section.property, counts, used, seen);
2027}
2028
2029fn refresh_para_ids_in_section_property(
2030    property: &mut SectionProperty,
2031    counts: &HashMap<String, usize>,
2032    used: &mut HashSet<String>,
2033    seen: &mut HashSet<String>,
2034) {
2035    if let Some((_, header)) = property.header.as_mut() {
2036        refresh_para_ids_in_header(header, counts, used, seen);
2037    }
2038    if let Some((_, header)) = property.first_header.as_mut() {
2039        refresh_para_ids_in_header(header, counts, used, seen);
2040    }
2041    if let Some((_, header)) = property.even_header.as_mut() {
2042        refresh_para_ids_in_header(header, counts, used, seen);
2043    }
2044    if let Some((_, footer)) = property.footer.as_mut() {
2045        refresh_para_ids_in_footer(footer, counts, used, seen);
2046    }
2047    if let Some((_, footer)) = property.first_footer.as_mut() {
2048        refresh_para_ids_in_footer(footer, counts, used, seen);
2049    }
2050    if let Some((_, footer)) = property.even_footer.as_mut() {
2051        refresh_para_ids_in_footer(footer, counts, used, seen);
2052    }
2053}
2054
2055fn refresh_para_ids_in_header(
2056    header: &mut Header,
2057    counts: &HashMap<String, usize>,
2058    used: &mut HashSet<String>,
2059    seen: &mut HashSet<String>,
2060) {
2061    for child in &mut header.children {
2062        match child {
2063            HeaderChild::Paragraph(paragraph) => {
2064                refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2065            }
2066            HeaderChild::Table(table) => refresh_para_ids_in_table(table, counts, used, seen),
2067            HeaderChild::StructuredDataTag(tag) => {
2068                refresh_para_ids_in_structured_data_tag(tag, counts, used, seen)
2069            }
2070        }
2071    }
2072}
2073
2074fn refresh_para_ids_in_footer(
2075    footer: &mut Footer,
2076    counts: &HashMap<String, usize>,
2077    used: &mut HashSet<String>,
2078    seen: &mut HashSet<String>,
2079) {
2080    for child in &mut footer.children {
2081        match child {
2082            FooterChild::Paragraph(paragraph) => {
2083                refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2084            }
2085            FooterChild::Table(table) => refresh_para_ids_in_table(table, counts, used, seen),
2086            FooterChild::StructuredDataTag(tag) => {
2087                refresh_para_ids_in_structured_data_tag(tag, counts, used, seen)
2088            }
2089        }
2090    }
2091}
2092
2093fn refresh_para_ids_in_toc(
2094    toc: &mut TableOfContents,
2095    counts: &HashMap<String, usize>,
2096    used: &mut HashSet<String>,
2097    seen: &mut HashSet<String>,
2098) {
2099    for child in &mut toc.before_contents {
2100        match child {
2101            TocContent::Paragraph(paragraph) => {
2102                refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2103            }
2104            TocContent::Table(table) => refresh_para_ids_in_table(table, counts, used, seen),
2105        }
2106    }
2107    for child in &mut toc.after_contents {
2108        match child {
2109            TocContent::Paragraph(paragraph) => {
2110                refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2111            }
2112            TocContent::Table(table) => refresh_para_ids_in_table(table, counts, used, seen),
2113        }
2114    }
2115}
2116
2117fn refresh_para_ids_in_table(
2118    table: &mut Table,
2119    counts: &HashMap<String, usize>,
2120    used: &mut HashSet<String>,
2121    seen: &mut HashSet<String>,
2122) {
2123    for TableChild::TableRow(row) in &mut table.rows {
2124        for TableRowChild::TableCell(cell) in &mut row.cells {
2125            for content in &mut cell.children {
2126                match content {
2127                    TableCellContent::Paragraph(paragraph) => {
2128                        refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2129                    }
2130                    TableCellContent::Table(table) => {
2131                        refresh_para_ids_in_table(table, counts, used, seen)
2132                    }
2133                    TableCellContent::StructuredDataTag(tag) => {
2134                        refresh_para_ids_in_structured_data_tag(tag, counts, used, seen)
2135                    }
2136                    TableCellContent::TableOfContents(toc) => {
2137                        refresh_para_ids_in_toc(toc, counts, used, seen)
2138                    }
2139                }
2140            }
2141        }
2142    }
2143}
2144
2145fn refresh_para_ids_in_paragraph(
2146    paragraph: &mut Paragraph,
2147    counts: &HashMap<String, usize>,
2148    used: &mut HashSet<String>,
2149    seen: &mut HashSet<String>,
2150) {
2151    ensure_unique_paragraph_id(paragraph, counts, used, seen);
2152
2153    for child in &mut paragraph.children {
2154        match child {
2155            ParagraphChild::CommentStart(c) => {
2156                refresh_para_ids_in_comment(&mut c.comment, counts, used, seen)
2157            }
2158            ParagraphChild::Insert(insert) => {
2159                refresh_para_ids_in_insert(insert, counts, used, seen)
2160            }
2161            ParagraphChild::Delete(delete) => {
2162                refresh_para_ids_in_delete(delete, counts, used, seen)
2163            }
2164            ParagraphChild::Hyperlink(hyperlink) => {
2165                refresh_para_ids_in_hyperlink(hyperlink, counts, used, seen)
2166            }
2167            ParagraphChild::StructuredDataTag(tag) => {
2168                refresh_para_ids_in_structured_data_tag(tag, counts, used, seen)
2169            }
2170            _ => {}
2171        }
2172    }
2173}
2174
2175fn refresh_para_ids_in_hyperlink(
2176    hyperlink: &mut Hyperlink,
2177    counts: &HashMap<String, usize>,
2178    used: &mut HashSet<String>,
2179    seen: &mut HashSet<String>,
2180) {
2181    for child in &mut hyperlink.children {
2182        match child {
2183            ParagraphChild::CommentStart(c) => {
2184                refresh_para_ids_in_comment(&mut c.comment, counts, used, seen)
2185            }
2186            ParagraphChild::Insert(insert) => {
2187                refresh_para_ids_in_insert(insert, counts, used, seen)
2188            }
2189            ParagraphChild::Delete(delete) => {
2190                refresh_para_ids_in_delete(delete, counts, used, seen)
2191            }
2192            ParagraphChild::StructuredDataTag(tag) => {
2193                refresh_para_ids_in_structured_data_tag(tag, counts, used, seen)
2194            }
2195            _ => {}
2196        }
2197    }
2198}
2199
2200fn refresh_para_ids_in_insert(
2201    insert: &mut Insert,
2202    counts: &HashMap<String, usize>,
2203    used: &mut HashSet<String>,
2204    seen: &mut HashSet<String>,
2205) {
2206    for child in &mut insert.children {
2207        match child {
2208            InsertChild::CommentStart(c) => {
2209                refresh_para_ids_in_comment(&mut c.comment, counts, used, seen)
2210            }
2211            InsertChild::Delete(delete) => refresh_para_ids_in_delete(delete, counts, used, seen),
2212            _ => {}
2213        }
2214    }
2215}
2216
2217fn refresh_para_ids_in_delete(
2218    delete: &mut Delete,
2219    counts: &HashMap<String, usize>,
2220    used: &mut HashSet<String>,
2221    seen: &mut HashSet<String>,
2222) {
2223    for child in &mut delete.children {
2224        if let DeleteChild::CommentStart(c) = child {
2225            refresh_para_ids_in_comment(&mut c.comment, counts, used, seen);
2226        }
2227    }
2228}
2229
2230fn refresh_para_ids_in_structured_data_tag(
2231    tag: &mut StructuredDataTag,
2232    counts: &HashMap<String, usize>,
2233    used: &mut HashSet<String>,
2234    seen: &mut HashSet<String>,
2235) {
2236    for child in &mut tag.children {
2237        match child {
2238            StructuredDataTagChild::Paragraph(paragraph) => {
2239                refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2240            }
2241            StructuredDataTagChild::Table(table) => {
2242                refresh_para_ids_in_table(table, counts, used, seen)
2243            }
2244            StructuredDataTagChild::CommentStart(c) => {
2245                refresh_para_ids_in_comment(&mut c.comment, counts, used, seen)
2246            }
2247            StructuredDataTagChild::StructuredDataTag(inner) => {
2248                refresh_para_ids_in_structured_data_tag(inner, counts, used, seen)
2249            }
2250            _ => {}
2251        }
2252    }
2253}
2254
2255fn refresh_para_ids_in_comment(
2256    comment: &mut Comment,
2257    counts: &HashMap<String, usize>,
2258    used: &mut HashSet<String>,
2259    seen: &mut HashSet<String>,
2260) {
2261    for child in &mut comment.children {
2262        match child {
2263            CommentChild::Paragraph(paragraph) => {
2264                refresh_para_ids_in_paragraph(paragraph, counts, used, seen)
2265            }
2266            CommentChild::Table(table) => refresh_para_ids_in_table(table, counts, used, seen),
2267        }
2268    }
2269}
2270
2271fn ensure_unique_paragraph_id(
2272    paragraph: &mut Paragraph,
2273    counts: &HashMap<String, usize>,
2274    used: &mut HashSet<String>,
2275    seen: &mut HashSet<String>,
2276) {
2277    let id = paragraph.id.clone();
2278    let count = counts.get(&id).copied().unwrap_or(0);
2279
2280    if !id.is_empty() && count <= 1 {
2281        return;
2282    }
2283    if !id.is_empty() && count > 1 && !seen.contains(&id) {
2284        seen.insert(id);
2285        return;
2286    }
2287
2288    let mut new_id = crate::generate_para_id();
2289    while used.contains(&new_id) {
2290        new_id = crate::generate_para_id();
2291    }
2292    paragraph.id = new_id.clone();
2293    used.insert(new_id);
2294}
2295
2296fn push_comment_and_comment_extended(
2297    comments: &mut Vec<Comment>,
2298    comments_extended: &mut Vec<CommentExtended>,
2299    comment_map: &HashMap<usize, String>,
2300    c: &CommentRangeStart,
2301) {
2302    let comment = c.get_comment_ref();
2303    for child in &comment.children {
2304        if let CommentChild::Paragraph(child) = child {
2305            let para_id = child.id.clone();
2306            comments.push(comment.clone());
2307            let comment_extended = CommentExtended::new(para_id);
2308            if let Some(parent_comment_id) = comment.parent_comment_id {
2309                if let Some(parent_para_id) = comment_map.get(&parent_comment_id) {
2310                    comments_extended
2311                        .push(comment_extended.parent_paragraph_id(parent_para_id.clone()));
2312                }
2313            } else {
2314                comments_extended.push(comment_extended);
2315            }
2316        }
2317        // TODO: Support table in comment
2318    }
2319}
2320
2321fn update_document_by_toc(
2322    document_children: Vec<DocumentChild>,
2323    styles: &Styles,
2324    toc: TableOfContents,
2325    toc_index: usize,
2326) -> Vec<DocumentChild> {
2327    let heading_map = styles.create_heading_style_map();
2328    let mut items = vec![];
2329    let mut children = vec![];
2330    let style_map: std::collections::HashMap<String, usize> = toc
2331        .instr
2332        .styles_with_levels
2333        .iter()
2334        .map(|sl| sl.0.clone())
2335        .collect();
2336
2337    if toc.instr.heading_styles_range.is_none() && !toc.instr.styles_with_levels.is_empty() {
2338        // INFO: if \t option set without heading styles ranges, Microsoft word does not show ToC items...
2339        return document_children;
2340    }
2341
2342    let (min, max) = toc.instr.heading_styles_range.unwrap_or((0, 9));
2343
2344    for child in document_children.into_iter() {
2345        match child {
2346            DocumentChild::Paragraph(mut paragraph) => {
2347                if let Some(heading_level) = paragraph
2348                    .property
2349                    .style
2350                    .as_ref()
2351                    .map(|p| p.val.to_string())
2352                    .and_then(|sid| heading_map.get(&sid))
2353                {
2354                    if min <= *heading_level && max >= *heading_level {
2355                        let toc_key = TocKey::generate();
2356                        items.push(
2357                            TableOfContentsItem::new()
2358                                .text(paragraph.raw_text())
2359                                .toc_key(&toc_key)
2360                                .level(*heading_level),
2361                        );
2362                        paragraph =
2363                            Box::new(paragraph.wrap_by_bookmark(generate_bookmark_id(), &toc_key));
2364                    }
2365
2366                    if let Some((_min, _max)) = toc.instr.tc_field_level_range {
2367                        // TODO: check tc field
2368                    }
2369                }
2370
2371                // Support \t option. Collect toc items if style id matched.
2372                if let Some(level) = paragraph
2373                    .property
2374                    .style
2375                    .as_ref()
2376                    .and_then(|s| style_map.get(&s.val))
2377                {
2378                    if min <= *level && max >= *level {
2379                        let toc_key = TocKey::generate();
2380                        items.push(
2381                            TableOfContentsItem::new()
2382                                .text(paragraph.raw_text())
2383                                .toc_key(&toc_key)
2384                                .level(*level),
2385                        );
2386                        paragraph =
2387                            Box::new(paragraph.wrap_by_bookmark(generate_bookmark_id(), &toc_key));
2388                    }
2389                }
2390
2391                children.push(DocumentChild::Paragraph(paragraph));
2392            }
2393            DocumentChild::Table(ref _table) => {
2394                // TODO:
2395                // for row in &table.rows {
2396                //     for cell in &row.cells {
2397                //         for content in &cell.children {
2398                //             match content {
2399                //                 TableCellContent::Paragraph(paragraph) => {}
2400                //                 TableCellContent::Table(_) => {
2401                //                     // TODO: Support table in table
2402                //                 }
2403                //             }
2404                //         }
2405                //     }
2406                // }
2407                children.push(child);
2408            }
2409            _ => {
2410                children.push(child);
2411            }
2412        }
2413    }
2414
2415    let mut toc = toc;
2416    toc.items = items;
2417    children[toc_index] = DocumentChild::TableOfContents(Box::new(toc));
2418    children
2419}