1use std::{collections::HashMap, str::FromStr};
2
3mod bookmark_id;
4mod build_xml;
5mod comments;
6mod comments_extended;
7mod content_types;
8mod custom_item;
9mod custom_item_property;
10mod custom_item_rels;
11mod doc_props;
12mod document;
13mod document_rels;
14mod elements;
15mod font_table;
16mod footer;
17mod footer_id;
18mod footer_rels;
19mod footnote_id;
20mod footnotes;
21mod header;
22mod header_id;
23mod header_rels;
24mod history_id;
25mod hyperlink_id;
26mod image_collector;
27mod numberings;
28mod paragraph_id;
29mod paragraph_property_change_id;
30mod pic_id;
31mod preset_styles;
32mod rels;
33mod settings;
34mod styles;
35mod taskpanes;
36mod taskpanes_rels;
37mod theme;
38mod toc_key;
39mod web_settings;
40mod webextension;
41mod xml_docx;
42
43pub use build_xml::BuildXML;
44pub(crate) use history_id::HistoryId;
45pub(crate) use hyperlink_id::*;
46pub(crate) use paragraph_id::*;
47pub(crate) use paragraph_property_change_id::ParagraphPropertyChangeId;
48pub(crate) use pic_id::*;
49
50pub use bookmark_id::*;
51pub use comments::*;
52pub use comments_extended::*;
53pub use content_types::*;
54pub use custom_item::*;
55pub use custom_item_property::*;
56pub use custom_item_rels::*;
57pub use doc_props::*;
58pub use document::*;
59pub use document_rels::*;
60pub use elements::*;
61pub use font_table::*;
62pub use footer::*;
63pub use footer_id::*;
64pub use footer_rels::*;
65pub use footnotes::*;
66pub use header::*;
67pub use header_id::*;
68pub use header_rels::*;
69pub use numberings::*;
70pub use rels::*;
71pub use settings::*;
72pub use styles::*;
73pub use taskpanes::*;
74pub use taskpanes_rels::*;
75pub use theme::*;
76pub use toc_key::*;
77pub use web_settings::*;
78pub use webextension::*;
79pub use xml_docx::*;
80
81use base64::Engine;
82use serde::{ser, Serialize};
83
84use self::image_collector::{collect_images_from_paragraph, collect_images_from_table};
85
86#[derive(Debug, Clone)]
87pub struct Image(pub Vec<u8>);
88
89#[derive(Debug, Clone)]
90pub struct Png(pub Vec<u8>);
91
92pub type ImageIdAndPath = (String, String);
93pub type ImageIdAndBuf = (String, Vec<u8>);
94
95impl ser::Serialize for Image {
96 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
97 where
98 S: ser::Serializer,
99 {
100 let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
101 serializer.collect_str(&base64)
102 }
103}
104
105impl ser::Serialize for Png {
106 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
107 where
108 S: ser::Serializer,
109 {
110 let base64 = base64::engine::general_purpose::STANDARD.encode(&self.0);
111 serializer.collect_str(&base64)
112 }
113}
114
115#[derive(Debug, Clone, Serialize)]
116#[serde(rename_all = "camelCase")]
117pub struct Docx {
118 pub content_type: ContentTypes,
119 pub rels: Rels,
120 pub document_rels: DocumentRels,
121 pub doc_props: DocProps,
122 pub styles: Styles,
123 pub document: Document,
124 pub comments: Comments,
125 pub numberings: Numberings,
126 pub settings: Settings,
127 pub font_table: FontTable,
128 pub media: Vec<(String, Vec<u8>)>,
129 pub comments_extended: CommentsExtended,
130 pub web_settings: WebSettings,
131 pub taskpanes: Option<Taskpanes>,
132 pub taskpanes_rels: TaskpanesRels,
133 pub web_extensions: Vec<WebExtension>,
134 pub custom_items: Vec<CustomItem>,
135 pub custom_item_props: Vec<CustomItemProperty>,
136 pub custom_item_rels: Vec<CustomItemRels>,
137 pub themes: Vec<Theme>,
139 pub images: Vec<(String, String, Image, Png)>,
141 pub hyperlinks: Vec<(String, String, String)>,
143 pub footnotes: Footnotes,
144}
145
146impl Default for Docx {
147 fn default() -> Self {
148 let content_type = ContentTypes::new().set_default();
149 let rels = Rels::new().set_default();
150 let doc_props = DocProps::new(CorePropsConfig::new());
151 let styles = Styles::new();
152 let document = Document::new();
153 let document_rels = DocumentRels::new();
154 let settings = Settings::new();
155 let font_table = FontTable::new();
156 let comments = Comments::new();
157 let numberings = Numberings::new();
158 let media = vec![];
159 let comments_extended = CommentsExtended::new();
160 let web_settings = WebSettings::new();
161 let footnotes = Footnotes::default();
162
163 Docx {
164 content_type,
165 rels,
166 document_rels,
167 doc_props,
168 styles,
169 document,
170 comments,
171 numberings,
172 settings,
173 font_table,
174 media,
175 comments_extended,
176 web_settings,
177 taskpanes: None,
178 taskpanes_rels: TaskpanesRels::new(),
179 web_extensions: vec![],
180 custom_items: vec![],
181 custom_item_props: vec![],
182 custom_item_rels: vec![],
183 themes: vec![],
184 images: vec![],
185 hyperlinks: vec![],
186 footnotes,
187 }
188 }
189}
190
191impl Docx {
192 pub fn new() -> Docx {
193 Default::default()
194 }
195
196 pub fn document(mut self, d: Document) -> Docx {
197 for child in &self.document.children {
198 match child {
199 DocumentChild::Paragraph(paragraph) => {
200 if paragraph.has_numbering {
201 self.document_rels.has_numberings = true;
202 }
203 }
204 DocumentChild::Table(table) => {
205 if table.has_numbering {
206 self.document_rels.has_numberings = true;
207 }
208 }
209 _ => {}
210 }
211 }
212 self.document = d;
213 self
214 }
215
216 pub fn styles(mut self, s: Styles) -> Self {
217 self.styles = s;
218 self
219 }
220
221 pub fn add_style(mut self, s: Style) -> Self {
222 self.styles = self.styles.add_style(s);
223 self
224 }
225
226 pub fn numberings(mut self, n: Numberings) -> Self {
227 self.numberings = n;
228 self
229 }
230
231 pub fn settings(mut self, s: Settings) -> Self {
232 self.settings = s;
233 self
234 }
235
236 pub(crate) fn web_settings(mut self, s: WebSettings) -> Self {
238 self.web_settings = s;
239 self
240 }
241
242 pub(crate) fn add_image(
244 mut self,
245 id: impl Into<String>,
246 path: impl Into<String>,
247 buf: Vec<u8>,
248 ) -> Self {
249 #[cfg(feature = "image")]
250 if let Ok(dimg) = image::load_from_memory(&buf) {
251 let mut png = std::io::Cursor::new(vec![]);
252 dimg.write_to(&mut png, image::ImageFormat::Png)
254 .expect("Unable to write dynamic image");
255
256 self.images
257 .push((id.into(), path.into(), Image(buf), Png(png.into_inner())));
258 }
259 #[cfg(not(feature = "image"))]
260 if buf.starts_with(&[137, 80, 78, 71, 13, 10, 26, 10]) {
262 self.images
263 .push((id.into(), path.into(), Image(buf.clone()), Png(buf)));
264 }
265 self
266 }
267
268 pub(crate) fn add_hyperlink(
270 mut self,
271 id: impl Into<String>,
272 path: impl Into<String>,
273 r#type: impl Into<String>,
274 ) -> Self {
275 self.hyperlinks
276 .push((id.into(), path.into(), r#type.into()));
277 self
278 }
279
280 pub fn comments(mut self, c: Comments) -> Self {
281 self.comments = c;
282 self
283 }
284
285 pub fn comments_extended(mut self, c: CommentsExtended) -> Self {
286 self.comments_extended = c;
287 self
288 }
289
290 pub fn add_paragraph(mut self, p: Paragraph) -> Docx {
291 if p.has_numbering {
292 self.document_rels.has_numberings = true;
295 }
296 self.document = self.document.add_paragraph(p);
297 self
298 }
299
300 pub fn add_structured_data_tag(mut self, t: StructuredDataTag) -> Docx {
301 if t.has_numbering {
302 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 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 if self.collect_footnotes() {
609 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 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 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 }
695 }
696
697 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 ¶graph.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 ¶graph.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 for child in &toc.before_contents {
778 if let TocContent::Paragraph(paragraph) = child {
779 for child in ¶graph.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 ¶graph.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 !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())); }
873 }
874
875 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 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 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 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(¶graph.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 ¶graph.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 }
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 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 }
1544 }
1545
1546 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 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}