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: xml::writer::EventWriter<W>,
49 ) -> xml::writer::Result<xml::writer::EventWriter<W>> {
50 let mut builder = XMLBuilder::from(stream)
51 .open_abstract_num(&self.id.to_string())?;
52
53 if let Some(ref multi_level_type) = self.multi_level_type {
55 builder = builder.multi_level_type(multi_level_type)?;
56 }
57
58 builder
59 .add_children(&self.levels)?
60 .close()?
61 .into_inner()
62 }
63}
64
65#[cfg(test)]
66mod tests {
67
68 use super::*;
69 #[cfg(test)]
70 use crate::documents::{Level, LevelJc, LevelText, NumberFormat, Start};
71 use pretty_assertions::assert_eq;
72 use std::str;
73
74 #[test]
75 fn test_numbering() {
76 let mut c = AbstractNumbering::new(0);
77 c = c.add_level(Level::new(
78 1,
79 Start::new(1),
80 NumberFormat::new("decimal"),
81 LevelText::new("%4."),
82 LevelJc::new("left"),
83 ));
84 let b = c.build();
85 assert_eq!(
86 str::from_utf8(&b).unwrap(),
87 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>"#
88 );
89 }
90
91 #[test]
92 fn test_numbering_json() {
93 let mut c = AbstractNumbering::new(0);
94 c = c
95 .add_level(Level::new(
96 1,
97 Start::new(1),
98 NumberFormat::new("decimal"),
99 LevelText::new("%4."),
100 LevelJc::new("left"),
101 ))
102 .num_style_link("style1");
103 assert_eq!(
104 serde_json::to_string(&c).unwrap(),
105 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}]}"#,
106 );
107 }
108}