docx_rs/documents/
rels.rs

1use serde::{Deserialize, Serialize};
2use std::io::Write;
3
4use crate::documents::BuildXML;
5use crate::xml_builder::*;
6
7#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Default)]
8pub struct Rels {
9    pub rels: Vec<(String, String, String)>,
10}
11
12impl Rels {
13    pub fn new() -> Rels {
14        Default::default()
15    }
16
17    pub fn set_default(mut self) -> Self {
18        self.rels.push((
19            "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"
20                .to_owned(),
21            "rId1".to_owned(),
22            "docProps/core.xml".to_owned(),
23        ));
24        self.rels.push(
25            ("http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties".to_owned(),
26            "rId2".to_owned(), "docProps/app.xml".to_owned()),
27        );
28        self.rels.push((
29            "http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument"
30                .to_owned(),
31            "rId3".to_owned(),
32            "word/document.xml".to_owned(),
33        ));
34        self.rels.push((
35            "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"
36                .to_owned(),
37            "rId4".to_owned(),
38            "docProps/custom.xml".to_owned(),
39        ));
40        self
41    }
42
43    pub fn add_taskpanes_rel(mut self) -> Self {
44        self = self.add_rel(
45            "http://schemas.microsoft.com/office/2011/relationships/webextensiontaskpanes",
46            "word/webextensions/taskpanes.xml",
47        );
48        self
49    }
50
51    pub fn add_rel(mut self, rel_type: impl Into<String>, target: impl Into<String>) -> Self {
52        self.rels.push((
53            rel_type.into(),
54            format!("rId{}", self.rels.len() + 1),
55            target.into(),
56        ));
57        self
58    }
59
60    pub fn find_target(&self, rel_type: &str) -> Option<&(String, String, String)> {
61        self.rels.iter().find(|rel| rel.0 == rel_type)
62    }
63}
64
65impl BuildXML for Rels {
66    fn build_to<W: Write>(
67        &self,
68        stream: xml::writer::EventWriter<W>,
69    ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
70        XMLBuilder::from(stream)
71            .declaration(None)?
72            .open_relationships("http://schemas.openxmlformats.org/package/2006/relationships")?
73            .apply_each(&self.rels, |(k, id, v), b| b.relationship(id, k, v))?
74            .close()?
75            .into_inner()
76    }
77}
78
79#[cfg(test)]
80mod tests {
81
82    use super::*;
83    #[cfg(test)]
84    use pretty_assertions::assert_eq;
85    use std::str;
86
87    #[test]
88    fn test_build() {
89        let c = Rels::new().set_default();
90        let b = c.build();
91        assert_eq!(
92            str::from_utf8(&b).unwrap(),
93            r#"<?xml version="1.0" encoding="UTF-8"?><Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships"><Relationship Id="rId1" Type="http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" Target="docProps/core.xml" /><Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties" Target="docProps/app.xml" /><Relationship Id="rId3" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/officeDocument" Target="word/document.xml" /><Relationship Id="rId4" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties" Target="docProps/custom.xml" /></Relationships>"#
94        );
95    }
96}