docx_rs/documents/
document_rels.rs

1use serde::Serialize;
2use std::io::Write;
3
4use super::*;
5use crate::documents::BuildXML;
6use crate::{escape::*, xml_builder::*};
7
8#[derive(Debug, Clone, PartialEq, Serialize, Default)]
9#[serde(rename_all = "camelCase")]
10pub struct DocumentRels {
11    pub has_comments: bool,
12    pub has_numberings: bool,
13    pub has_footnotes: bool,
14    pub images: Vec<(String, String)>,
15    pub hyperlinks: Vec<(String, String, String)>,
16    pub custom_xml_count: usize,
17    pub header_count: usize,
18    pub footer_count: usize,
19}
20
21impl DocumentRels {
22    pub fn new() -> DocumentRels {
23        Default::default()
24    }
25
26    pub fn add_custom_item(mut self) -> Self {
27        self.custom_xml_count += 1;
28        self
29    }
30
31    pub fn add_image(mut self, id: impl Into<String>, path: impl Into<String>) -> Self {
32        self.images.push((id.into(), path.into()));
33        self
34    }
35
36    pub fn add_hyperlinks(
37        mut self,
38        id: impl Into<String>,
39        path: impl Into<String>,
40        r#type: impl Into<String>,
41    ) -> Self {
42        self.hyperlinks
43            .push((id.into(), escape(&path.into()), r#type.into()));
44        self
45    }
46}
47
48impl BuildXML for DocumentRels {
49    fn build_to<W: Write>(
50        &self,
51        stream: xml::writer::EventWriter<W>,
52    ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
53        XMLBuilder::from(stream)
54            .declaration(None)?
55            .open_relationships("http://schemas.openxmlformats.org/package/2006/relationships")?
56            .relationship(
57                "rId1",
58                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/styles",
59                "styles.xml",
60            )?
61            .relationship(
62                "rId2",
63                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/fontTable",
64                "fontTable.xml",
65            )?
66            .relationship(
67                "rId3",
68                "http://schemas.openxmlformats.org/officeDocument/2006/relationships/settings",
69                "settings.xml",
70            )?
71            .relationship(
72                "rId5",
73                "http://schemas.microsoft.com/office/2011/relationships/commentsExtended",
74                "commentsExtended.xml",
75            )?
76            .apply_if(self.has_comments, |b| {
77                b.relationship(
78                    "rId6",
79                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/comments",
80                    "comments.xml",
81                )
82            })?
83            .apply_if(self.has_numberings, |b| {
84                b.relationship(
85                    "rId7",
86                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/numbering",
87                    "numbering.xml",
88                )
89            })?
90            .apply_if(self.has_footnotes, |b| {
91                b.relationship(
92                    "rId8",
93                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footnotes",
94                    "footnotes.xml",
95                )
96            })?
97            .apply_each(0..self.header_count, |i, b| {
98                b.relationship(
99                    &create_header_rid(i + 1),
100                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header",
101                    &format!("header{}.xml", i + 1),
102                )
103            })?
104            .apply_each(0..self.footer_count, |i, b| {
105                b.relationship(
106                    &create_footer_rid(i + 1),
107                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/footer",
108                    &format!("footer{}.xml", i + 1),
109                )
110            })?
111            .apply_each(0..self.custom_xml_count, |i, b| {
112                b.relationship(
113                    &format!("rId{}", i + 8),
114                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/customXml",
115                    &format!("../customXml/item{}.xml", i + 1),
116                )
117            })?
118            .apply_each(self.images.iter(), |(id, path), b| {
119                b.relationship(
120                    id,
121                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
122                    path,
123                )
124            })?
125            .apply_each(self.hyperlinks.iter(), |(id, path, r#type), b| {
126                b.relationship_with_mode(
127                    id,
128                    "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink",
129                    path,
130                    r#type,
131                )
132            })?
133            .close()?
134            .into_inner()
135    }
136}