docx_rs/documents/elements/
abstract_numbering.rs1use crate::documents::{BuildXML, Level};
2use crate::xml_builder::*;
3use std::io::Write;
4
5use serde::Serialize;
6
7#[derive(Debug, Clone, PartialEq, Serialize)]
8#[serde(rename_all = "camelCase")]
9pub struct AbstractNumbering {
10 pub id: usize,
11 pub style_link: Option<String>,
12 pub num_style_link: Option<String>,
13 pub levels: Vec<Level>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub multi_level_type: Option<String>,
16}
17
18impl AbstractNumbering {
19 pub fn new(id: usize) -> Self {
20 Self {
21 id,
22 style_link: None,
23 num_style_link: None,
24 levels: vec![],
25 multi_level_type: None,
26 }
27 }
28
29 pub fn add_level(mut self, level: Level) -> Self {
30 self.levels.push(level);
31 self
32 }
33
34 pub fn num_style_link(mut self, link: impl Into<String>) -> Self {
35 self.num_style_link = Some(link.into());
36 self
37 }
38
39 pub fn style_link(mut self, link: impl Into<String>) -> Self {
40 self.style_link = Some(link.into());
41 self
42 }
43}
44
45impl BuildXML for AbstractNumbering {
46 fn build_to<W: Write>(
47 &self,
48 stream: crate::xml::writer::EventWriter<W>,
49 ) -> crate::xml::writer::Result<crate::xml::writer::EventWriter<W>> {
50 let mut builder = XMLBuilder::from(stream).open_abstract_num(&self.id.to_string())?;
51
52 if let Some(ref multi_level_type) = self.multi_level_type {
54 builder = builder.multi_level_type(multi_level_type)?;
55 }
56
57 builder.add_children(&self.levels)?.close()?.into_inner()
58 }
59}
60
61#[cfg(test)]
62mod tests {
63
64 use super::*;
65 #[cfg(test)]
66 use crate::documents::{Level, LevelJc, LevelText, NumberFormat, Start};
67 use pretty_assertions::assert_eq;
68 use std::str;
69
70 #[test]
71 fn test_numbering() {
72 let mut c = AbstractNumbering::new(0);
73 c = c.add_level(Level::new(
74 1,
75 Start::new(1),
76 NumberFormat::new("decimal"),
77 LevelText::new("%4."),
78 LevelJc::new("left"),
79 ));
80 let b = c.build();
81 assert_eq!(
82 str::from_utf8(&b).unwrap(),
83 r#"<w:abstractNum w:abstractNumId="0"><w:lvl w:ilvl="1"><w:start w:val="1" /><w:numFmt w:val="decimal" /><w:lvlText w:val="%4." /><w:lvlJc w:val="left" /><w:pPr><w:rPr /></w:pPr><w:rPr /></w:lvl></w:abstractNum>"#
84 );
85 }
86
87 #[test]
88 fn test_numbering_json() {
89 let mut c = AbstractNumbering::new(0);
90 c = c
91 .add_level(Level::new(
92 1,
93 Start::new(1),
94 NumberFormat::new("decimal"),
95 LevelText::new("%4."),
96 LevelJc::new("left"),
97 ))
98 .num_style_link("style1");
99 assert_eq!(
100 serde_json::to_string(&c).unwrap(),
101 r#"{"id":0,"styleLink":null,"numStyleLink":"style1","levels":[{"level":1,"start":1,"format":"decimal","text":"%4.","jc":"left","paragraphProperty":{"runProperty":{},"tabs":[]},"runProperty":{},"suffix":"tab","pstyle":null,"levelRestart":null}]}"#,
102 );
103 }
104}