docx_rust/document/
footnotes.rs

1//! FootNotes part
2//!
3//! The corresponding ZIP item is `/word/footnotes.xml`.
4//!
5
6use hard_xml::{XmlRead, XmlResult, XmlWrite, XmlWriter};
7use std::borrow::Cow;
8use std::io::Write;
9
10use crate::schema::{SCHEMA_MAIN, SCHEMA_WORDML_14};
11use crate::{__string_enum, __xml_test_suites};
12
13use crate::document::BodyContent;
14
15#[derive(Debug, Default, XmlRead, Clone)]
16#[cfg_attr(test, derive(PartialEq))]
17#[xml(tag = "w:footnotes")]
18pub struct FootNotes<'a> {
19    #[xml(child = "w:footnote")]
20    pub content: Vec<FootNote<'a>>,
21}
22
23#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
24#[cfg_attr(test, derive(PartialEq))]
25#[xml(tag = "w:footnote")]
26pub struct FootNote<'a> {
27    #[xml(attr = "w:type")]
28    pub ty: Option<NoteSeparator>,
29    #[xml(attr = "w:id")]
30    pub id: Option<isize>,
31    #[xml(child = "w:sdt", child = "w:p", child = "w:tbl", child = "w:sectPr")]
32    pub content: Vec<BodyContent<'a>>,
33}
34
35#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
36#[cfg_attr(test, derive(PartialEq))]
37#[xml(tag = "w:footnoteRef")]
38pub struct FootnoteRef;
39
40#[derive(Debug, Default, XmlRead, XmlWrite, Clone)]
41#[cfg_attr(test, derive(PartialEq))]
42#[xml(tag = "w:footnoteReference")]
43pub struct FootnoteReference<'a> {
44    /// Specifies the HeaderReference type of this HeaderReference.
45    #[xml(attr = "w:customMarkFollows")]
46    pub supress_reference_mark: Option<bool>,
47    #[xml(attr = "w:id")]
48    pub id: Option<Cow<'a, str>>,
49}
50
51impl<'a> FootNote<'a> {
52    pub fn push<T: Into<BodyContent<'a>>>(&mut self, content: T) -> &mut Self {
53        self.content.push(content.into());
54        self
55    }
56}
57
58impl<'a> XmlWrite for FootNotes<'a> {
59    fn to_writer<W: Write>(&self, writer: &mut XmlWriter<W>) -> XmlResult<()> {
60        let FootNotes { content } = self;
61
62        log::debug!("[FootNotes] Started writing.");
63        let _ = write!(writer.inner, "{}", crate::schema::SCHEMA_XML);
64
65        writer.write_element_start("w:footnotes")?;
66
67        writer.write_attribute("xmlns:w", SCHEMA_MAIN)?;
68
69        writer.write_attribute("xmlns:w14", SCHEMA_WORDML_14)?;
70
71        writer.write_element_end_open()?;
72
73        for c in content {
74            c.to_writer(writer)?;
75        }
76
77        writer.write_element_end_close("w:footnotes")?;
78
79        log::debug!("[Document] Finished writing.");
80
81        Ok(())
82    }
83}
84
85#[derive(Debug, Clone)]
86#[cfg_attr(test, derive(PartialEq))]
87pub enum NoteSeparator {
88    Separator,
89    ContinuationSeparator,
90    ContinuationNotice,
91}
92
93__string_enum! {
94    NoteSeparator {
95        Separator = "separator",
96        ContinuationSeparator = "continuationSeparator",
97        ContinuationNotice = "continuationNotice",
98    }
99}
100
101__xml_test_suites!(
102    FootNotes,
103    FootNotes::default(),
104    format!(
105        r#"{}<w:footnotes xmlns:w="{}" xmlns:w14="{}"></w:footnotes>"#,
106        crate::schema::SCHEMA_XML,
107        SCHEMA_MAIN,
108        SCHEMA_WORDML_14
109    )
110    .as_str(),
111);