docx_rs/documents/elements/
level.rs1use crate::documents::*;
2use crate::types::*;
3use crate::xml_builder::*;
4
5use serde::Serialize;
6
7#[derive(Debug, Clone, PartialEq, Serialize)]
8#[serde(rename_all = "camelCase")]
9pub struct Level {
10 pub level: usize,
11 pub start: Start,
12 pub format: NumberFormat,
13 pub text: LevelText,
14 pub jc: LevelJc,
15 pub paragraph_property: ParagraphProperty,
16 pub run_property: RunProperty,
17 pub suffix: LevelSuffixType,
18 pub pstyle: Option<String>,
19 pub level_restart: Option<LevelRestart>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub is_lgl: Option<IsLgl>,
22}
23
24impl Level {
25 pub fn new(
26 level: usize,
27 start: Start,
28 format: NumberFormat,
29 text: LevelText,
30 jc: LevelJc,
31 ) -> Level {
32 Self {
33 level,
34 start,
35 format,
36 text,
37 jc,
38 paragraph_property: ParagraphProperty::new(),
39 run_property: RunProperty::new(),
40 suffix: LevelSuffixType::Tab,
41 pstyle: None,
42 level_restart: None,
43 is_lgl: None,
44 }
45 }
46
47 pub fn indent(
48 mut self,
49 left: Option<i32>,
50 special_indent: Option<SpecialIndentType>,
51 end: Option<i32>,
52 start_chars: Option<i32>,
53 ) -> Self {
54 self.paragraph_property =
55 self.paragraph_property
56 .indent(left, special_indent, end, start_chars);
57 self
58 }
59
60 pub fn paragraph_style(mut self, style_id: impl Into<String>) -> Self {
61 self.pstyle = Some(style_id.into());
62 self
63 }
64
65 pub fn suffix(mut self, s: LevelSuffixType) -> Self {
66 self.suffix = s;
67 self
68 }
69
70 pub fn size(mut self, size: usize) -> Self {
72 self.run_property = self.run_property.size(size);
73 self
74 }
75
76 pub fn spacing(mut self, v: i32) -> Self {
77 self.run_property = self.run_property.spacing(v);
78 self
79 }
80
81 pub fn color(mut self, color: impl Into<String>) -> Self {
82 self.run_property = self.run_property.color(color);
83 self
84 }
85
86 pub fn highlight(mut self, color: impl Into<String>) -> Self {
87 self.run_property = self.run_property.highlight(color);
88 self
89 }
90
91 pub fn bold(mut self) -> Self {
92 self.run_property = self.run_property.bold();
93 self
94 }
95
96 pub fn italic(mut self) -> Self {
97 self.run_property = self.run_property.italic();
98 self
99 }
100
101 pub fn underline(mut self, line_type: impl Into<String>) -> Self {
102 self.run_property = self.run_property.underline(line_type);
103 self
104 }
105
106 pub fn vanish(mut self) -> Self {
107 self.run_property = self.run_property.vanish();
108 self
109 }
110
111 pub fn fonts(mut self, f: RunFonts) -> Self {
112 self.run_property = self.run_property.fonts(f);
113 self
114 }
115
116 pub fn level_restart(mut self, v: u32) -> Self {
117 self.level_restart = Some(LevelRestart::new(v));
118 self
119 }
120
121 pub fn is_lgl(mut self) -> Self {
122 self.is_lgl = Some(IsLgl::new());
123 self
124 }
125}
126
127impl BuildXML for Level {
128 fn build(&self) -> Vec<u8> {
129 let mut b = XMLBuilder::new()
130 .open_level(&format!("{}", self.level))
131 .add_child(&self.start)
132 .add_child(&self.format)
133 .add_child(&self.text)
134 .add_child(&self.jc)
135 .add_child(&self.paragraph_property)
136 .add_child(&self.run_property)
137 .add_optional_child(&self.level_restart)
138 .add_optional_child(&self.is_lgl);
139
140 if self.suffix != LevelSuffixType::Tab {
141 b = b.suffix(&self.suffix.to_string());
142 }
143
144 b.close().build()
145 }
146}
147
148#[cfg(test)]
149mod tests {
150
151 use super::*;
152 #[cfg(test)]
153 use pretty_assertions::assert_eq;
154 use std::str;
155
156 #[test]
157 fn test_level() {
158 let b = Level::new(
159 1,
160 Start::new(1),
161 NumberFormat::new("decimal"),
162 LevelText::new("%4."),
163 LevelJc::new("left"),
164 )
165 .build();
166 assert_eq!(
167 str::from_utf8(&b).unwrap(),
168 r#"<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>"#
169 );
170 }
171
172 #[test]
173 fn test_level_indent() {
174 let b = Level::new(
175 1,
176 Start::new(1),
177 NumberFormat::new("decimal"),
178 LevelText::new("%4."),
179 LevelJc::new("left"),
180 )
181 .indent(Some(320), Some(SpecialIndentType::Hanging(200)), None, None)
182 .build();
183 assert_eq!(
184 str::from_utf8(&b).unwrap(),
185 r#"<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:ind w:left="320" w:right="0" w:hanging="200" /></w:pPr><w:rPr /></w:lvl>"#
186 );
187 }
188 #[test]
189 fn test_level_with_suff() {
190 let b = Level::new(
191 1,
192 Start::new(1),
193 NumberFormat::new("decimal"),
194 LevelText::new("%4."),
195 LevelJc::new("left"),
196 )
197 .suffix(LevelSuffixType::Space)
198 .build();
199 assert_eq!(
200 str::from_utf8(&b).unwrap(),
201 r#"<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:suff w:val="space" />
202</w:lvl>"#
203 );
204 }
205}