Skip to main content

docx_rs/zipper/
mod.rs

1use crate::XMLDocx;
2
3use std::io::prelude::*;
4use std::io::Seek;
5use zip::write::FileOptions;
6
7pub fn zip<W>(w: W, xml: XMLDocx) -> zip::result::ZipResult<()>
8where
9    W: Write + Seek,
10{
11    let mut zip = zip::ZipWriter::new(w);
12
13    zip.add_directory("word/", Default::default())?;
14    zip.add_directory("word/_rels", Default::default())?;
15    zip.add_directory("_rels/", Default::default())?;
16    zip.add_directory("docProps/", Default::default())?;
17
18    let options = FileOptions::default()
19        .compression_method(zip::CompressionMethod::Stored)
20        .unix_permissions(0o755);
21
22    zip.start_file("[Content_Types].xml", options)?;
23    zip.write_all(&xml.content_type)?;
24    zip.start_file("_rels/.rels", options)?;
25    zip.write_all(&xml.rels)?;
26    zip.start_file("docProps/app.xml", options)?;
27    zip.write_all(&xml.doc_props.app)?;
28    zip.start_file("docProps/core.xml", options)?;
29    zip.write_all(&xml.doc_props.core)?;
30    zip.start_file("docProps/custom.xml", options)?;
31    zip.write_all(&xml.doc_props.custom)?;
32    zip.start_file("word/_rels/document.xml.rels", options)?;
33    zip.write_all(&xml.document_rels)?;
34    zip.start_file("word/document.xml", options)?;
35    zip.write_all(&xml.document)?;
36    zip.start_file("word/styles.xml", options)?;
37    zip.write_all(&xml.styles)?;
38    zip.start_file("word/settings.xml", options)?;
39    zip.write_all(&xml.settings)?;
40    zip.start_file("word/fontTable.xml", options)?;
41    zip.write_all(&xml.font_table)?;
42    zip.start_file("word/comments.xml", options)?;
43    zip.write_all(&xml.comments)?;
44    zip.start_file("word/numbering.xml", options)?;
45    zip.write_all(&xml.numberings)?;
46    zip.start_file("word/commentsExtended.xml", options)?;
47    zip.write_all(&xml.comments_extended)?;
48    zip.start_file("word/footnotes.xml", options)?;
49    zip.write_all(&xml.footnotes)?;
50
51    for (i, h) in xml.headers.iter().enumerate() {
52        zip.start_file(format!("word/header{}.xml", i + 1), options)?;
53        zip.write_all(h)?;
54
55        if let Some(rels) = xml.header_rels.get(i) {
56            zip.start_file(format!("word/_rels/header{}.xml.rels", i + 1), options)?;
57            zip.write_all(rels)?;
58        }
59    }
60
61    for (i, h) in xml.footers.iter().enumerate() {
62        zip.start_file(format!("word/footer{}.xml", i + 1), options)?;
63        zip.write_all(h)?;
64
65        if let Some(rels) = xml.footer_rels.get(i) {
66            zip.start_file(format!("word/_rels/footer{}.xml.rels", i + 1), options)?;
67            zip.write_all(rels)?;
68        }
69    }
70
71    if !xml.media.is_empty() {
72        zip.add_directory("word/media/", Default::default())?;
73        for m in xml.media {
74            // For now only png supported
75            zip.start_file(format!("word/media/{}.png", m.0), options)?;
76            zip.write_all(&m.1)?;
77        }
78    }
79
80    // For now support only taskpanes
81    if let Some(taskpanes) = xml.taskpanes {
82        zip.add_directory("word/webextensions/", Default::default())?;
83        zip.start_file("word/webextensions/taskpanes.xml", options)?;
84        zip.write_all(&taskpanes)?;
85
86        zip.add_directory("word/webextensions/_rels", Default::default())?;
87        zip.start_file("word/webextensions/_rels/taskpanes.xml.rels", options)?;
88        zip.write_all(&xml.taskpanes_rels)?;
89
90        for (i, ext) in xml.web_extensions.iter().enumerate() {
91            zip.start_file(
92                format!("word/webextensions/webextension{}.xml", i + 1),
93                options,
94            )?;
95            zip.write_all(ext)?;
96        }
97    }
98
99    if !xml.custom_items.is_empty() {
100        zip.add_directory("customXml/_rels", Default::default())?;
101    }
102
103    for (i, item) in xml.custom_items.into_iter().enumerate() {
104        let n = i + 1;
105        zip.start_file(format!("customXml/_rels/item{}.xml.rels", n), options)?;
106        zip.write_all(&xml.custom_item_rels[i])?;
107        zip.start_file(format!("customXml/item{}.xml", n), options)?;
108        zip.write_all(&item)?;
109        zip.start_file(format!("customXml/itemProps{}.xml", n), options)?;
110        zip.write_all(&xml.custom_item_props[i])?;
111    }
112
113    zip.finish()?;
114    Ok(())
115}