ppt_rs/generator/text/
run.rs1use super::format::TextFormat;
4use super::escape_xml;
5use crate::core::ToXml;
6
7#[derive(Clone, Debug)]
9pub struct Run {
10 pub text: String,
11 pub format: TextFormat,
12}
13
14impl Run {
15 pub fn new(text: &str) -> Self {
17 Run {
18 text: text.to_string(),
19 format: TextFormat::default(),
20 }
21 }
22
23 pub fn with_format(mut self, format: TextFormat) -> Self {
25 self.format = format;
26 self
27 }
28
29 pub fn bold(mut self) -> Self {
31 self.format.bold = true;
32 self
33 }
34
35 pub fn italic(mut self) -> Self {
37 self.format.italic = true;
38 self
39 }
40
41 pub fn underline(mut self) -> Self {
43 self.format.underline = true;
44 self
45 }
46
47 pub fn color(mut self, hex: &str) -> Self {
49 self.format.color = Some(hex.trim_start_matches('#').to_uppercase());
50 self
51 }
52
53 pub fn size(mut self, points: u32) -> Self {
55 self.format.font_size = Some(points);
56 self
57 }
58
59 pub fn font(mut self, family: &str) -> Self {
61 self.format.font_family = Some(family.to_string());
62 self
63 }
64
65 pub fn to_xml(&self) -> String {
67 let size = self.format.font_size.unwrap_or(18) * 100;
68 let bold = if self.format.bold { "1" } else { "0" };
69 let italic = if self.format.italic { "1" } else { "0" };
70 let underline = if self.format.underline { " u=\"sng\"" } else { "" };
71
72 let color_xml = self.format.color.as_ref()
73 .map(|c| format!(r#"<a:solidFill><a:srgbClr val="{}"/></a:solidFill>"#, c))
74 .unwrap_or_default();
75
76 let font_xml = self.format.font_family.as_ref()
77 .map(|f| format!(r#"<a:latin typeface="{}"/>"#, escape_xml(f)))
78 .unwrap_or_default();
79
80 format!(
81 r#"<a:r><a:rPr lang="en-US" sz="{}" b="{}" i="{}"{} dirty="0">{}{}</a:rPr><a:t>{}</a:t></a:r>"#,
82 size, bold, italic, underline, color_xml, font_xml, escape_xml(&self.text)
83 )
84 }
85}
86
87impl ToXml for Run {
88 fn to_xml(&self) -> String {
89 Run::to_xml(self)
90 }
91}
92
93#[cfg(test)]
94mod tests {
95 use super::*;
96
97 #[test]
98 fn test_run_to_xml() {
99 let run = Run::new("Hello").bold().color("FF0000").size(24);
100 let xml = run.to_xml();
101
102 assert!(xml.contains("Hello"));
103 assert!(xml.contains("b=\"1\""));
104 assert!(xml.contains("FF0000"));
105 assert!(xml.contains("sz=\"2400\""));
106 }
107
108 #[test]
109 fn test_font_family() {
110 let run = Run::new("Arial text").font("Arial");
111 let xml = run.to_xml();
112
113 assert!(xml.contains("typeface=\"Arial\""));
114 }
115}