docx_rs/documents/
mod.rs

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