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 pub themes: Vec<Theme>,
142 pub images: Vec<(String, String, Image, Png)>,
144 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 pub(crate) fn web_settings(mut self, s: WebSettings) -> Self {
241 self.web_settings = s;
242 self
243 }
244
245 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 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 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 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 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 self.document_rels.has_numberings = true;
308 }
309
310 let mut new_section = s;
311
312 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 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 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 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 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 if self.collect_footnotes() {
801 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 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 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 }
897 }
898
899 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 ¶graph.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 ¶graph.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 for child in &toc.before_contents {
989 if let TocContent::Paragraph(paragraph) = child {
990 for child in ¶graph.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 ¶graph.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 !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())); }
1084 }
1085
1086 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 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 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 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(¶graph.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 ¶graph.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 ¶graph.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 §ion.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(§ion.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 ¶graph.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 }
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 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 }
2369 }
2370
2371 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 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}