ppt_rs/generator/text/
format.rs1#[derive(Clone, Debug, Default)]
5pub struct TextFormat {
6 pub bold: bool,
7 pub italic: bool,
8 pub underline: bool,
9 pub color: Option<String>, pub font_size: Option<u32>, pub font_family: Option<String>, }
13
14impl TextFormat {
15 pub fn new() -> Self {
17 Self::default()
18 }
19
20 pub fn bold(mut self) -> Self {
22 self.bold = true;
23 self
24 }
25
26 pub fn italic(mut self) -> Self {
28 self.italic = true;
29 self
30 }
31
32 pub fn underline(mut self) -> Self {
34 self.underline = true;
35 self
36 }
37
38 pub fn color(mut self, hex_color: &str) -> Self {
40 self.color = Some(hex_color.trim_start_matches('#').to_uppercase());
41 self
42 }
43
44 pub fn font_size(mut self, size: u32) -> Self {
46 self.font_size = Some(size);
47 self
48 }
49
50 pub fn font_family(mut self, family: &str) -> Self {
52 self.font_family = Some(family.to_string());
53 self
54 }
55
56 pub fn to_xml_attrs(&self) -> String {
58 let mut attrs = String::new();
59
60 if self.bold {
61 attrs.push_str(" b=\"1\"");
62 }
63
64 if self.italic {
65 attrs.push_str(" i=\"1\"");
66 }
67
68 if self.underline {
69 attrs.push_str(" u=\"sng\"");
70 }
71
72 if let Some(size) = self.font_size {
73 attrs.push_str(&format!(" sz=\"{}\"", size * 100));
74 }
75
76 attrs
77 }
78}
79
80#[derive(Clone, Debug)]
82pub struct FormattedText {
83 pub text: String,
84 pub format: TextFormat,
85}
86
87impl FormattedText {
88 pub fn new(text: &str) -> Self {
90 FormattedText {
91 text: text.to_string(),
92 format: TextFormat::default(),
93 }
94 }
95
96 pub fn with_format(mut self, format: TextFormat) -> Self {
98 self.format = format;
99 self
100 }
101
102 pub fn bold(mut self) -> Self {
104 self.format = self.format.bold();
105 self
106 }
107
108 pub fn italic(mut self) -> Self {
110 self.format = self.format.italic();
111 self
112 }
113
114 pub fn underline(mut self) -> Self {
116 self.format = self.format.underline();
117 self
118 }
119
120 pub fn color(mut self, hex_color: &str) -> Self {
122 self.format = self.format.color(hex_color);
123 self
124 }
125
126 pub fn font_size(mut self, size: u32) -> Self {
128 self.format = self.format.font_size(size);
129 self
130 }
131}
132
133pub fn color_to_xml(hex_color: &str) -> String {
135 let clean_color = hex_color.trim_start_matches('#').to_uppercase();
136 format!("<a:solidFill><a:srgbClr val=\"{}\"/></a:solidFill>", clean_color)
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_text_format_builder() {
145 let format = TextFormat::new()
146 .bold()
147 .italic()
148 .color("FF0000")
149 .font_size(24);
150
151 assert!(format.bold);
152 assert!(format.italic);
153 assert_eq!(format.color, Some("FF0000".to_string()));
154 assert_eq!(format.font_size, Some(24));
155 }
156
157 #[test]
158 fn test_formatted_text_builder() {
159 let text = FormattedText::new("Hello")
160 .bold()
161 .italic()
162 .color("0000FF");
163
164 assert_eq!(text.text, "Hello");
165 assert!(text.format.bold);
166 assert!(text.format.italic);
167 assert_eq!(text.format.color, Some("0000FF".to_string()));
168 }
169
170 #[test]
171 fn test_format_to_xml_attrs() {
172 let format = TextFormat::new().bold().italic().font_size(24);
173 let attrs = format.to_xml_attrs();
174 assert!(attrs.contains("b=\"1\""));
175 assert!(attrs.contains("i=\"1\""));
176 assert!(attrs.contains("sz=\"2400\""));
177 }
178
179 #[test]
180 fn test_color_to_xml() {
181 let xml = color_to_xml("FF0000");
182 assert!(xml.contains("FF0000"));
183 assert!(xml.contains("srgbClr"));
184 }
185}