ppt_rs/generator/slide_xml/
mod.rs1mod common;
12mod layouts;
13mod content;
14
15use super::slide_content::{SlideContent, SlideLayout};
16
17pub use common::create_slide_rels_xml;
18
19pub fn create_slide_xml(slide_num: usize, title: &str) -> String {
21 let slide_title = if slide_num == 1 {
22 title.to_string()
23 } else {
24 format!("Slide {slide_num}")
25 };
26
27 format!(
28 r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
29<p:sld xmlns:a="http://schemas.openxmlformats.org/drawingml/2006/main" xmlns:r="http://schemas.openxmlformats.org/officeDocument/2006/relationships" xmlns:p="http://schemas.openxmlformats.org/presentationml/2006/main">
30<p:cSld>
31<p:spTree>
32<p:nvGrpSpPr>
33<p:cNvPr id="1" name=""/>
34<p:cNvGrpSpPr/>
35<p:nvPr/>
36</p:nvGrpSpPr>
37<p:grpSpPr>
38<a:xfrm>
39<a:off x="0" y="0"/>
40<a:ext cx="0" cy="0"/>
41<a:chOff x="0" y="0"/>
42<a:chExt cx="0" cy="0"/>
43</a:xfrm>
44</p:grpSpPr>
45<p:sp>
46<p:nvSpPr>
47<p:cNvPr id="2" name="Title 1"/>
48<p:cNvSpPr>
49<a:spLocks noGrp="1"/>
50</p:cNvSpPr>
51<p:nvPr>
52<p:ph type="ctrTitle"/>
53</p:nvPr>
54</p:nvSpPr>
55<p:spPr/>
56<p:txBody>
57<a:bodyPr/>
58<a:lstStyle/>
59<a:p>
60<a:r>
61<a:rPr lang="en-US"/>
62<a:t>{slide_title}</a:t>
63</a:r>
64<a:endParaRPr lang="en-US"/>
65</a:p>
66</p:txBody>
67</p:sp>
68</p:spTree>
69</p:cSld>
70<p:clrMapOvr>
71<a:masterClrMapping/>
72</p:clrMapOvr>
73</p:sld>"#
74 )
75}
76
77pub fn create_slide_xml_with_content(
79 _slide_num: usize,
80 content: &SlideContent,
81 chart_rids: &[String],
82 ink_rel_id: Option<&str>,
83) -> String {
84 let mut xml = match content.layout {
85 SlideLayout::Blank => layouts::create_blank_slide(content, chart_rids, ink_rel_id),
86 SlideLayout::TitleOnly => layouts::create_title_only_slide(content, chart_rids, ink_rel_id),
87 SlideLayout::CenteredTitle => layouts::create_centered_title_slide(content, chart_rids, ink_rel_id),
88 SlideLayout::TitleAndBigContent => layouts::create_title_and_big_content_slide(content, chart_rids, ink_rel_id),
89 SlideLayout::TwoColumn => layouts::create_two_column_slide(content, chart_rids, ink_rel_id),
90 SlideLayout::SectionHeader => layouts::create_section_header_slide(content, chart_rids, ink_rel_id),
91 SlideLayout::TitleAndContent => layouts::create_title_and_content_slide(content, chart_rids, ink_rel_id),
92 };
93
94 let transition_xml = content.transition.to_xml();
96 if !transition_xml.is_empty()
97 && let Some(pos) = xml.rfind("</p:sld>") {
98 xml.insert_str(pos, &transition_xml);
99 }
100
101 xml
102}
103
104#[cfg(test)]
105mod tests {
106 use crate::generator::slide::formatting::parse_inline_formatting;
107
108 #[test]
109 fn test_parse_inline_formatting_plain() {
110 let segments = parse_inline_formatting("Hello world");
111 assert_eq!(segments.len(), 1);
112 assert_eq!(segments[0].text, "Hello world");
113 assert!(!segments[0].bold);
114 assert!(!segments[0].italic);
115 }
116
117 #[test]
118 fn test_parse_inline_formatting_bold() {
119 let segments = parse_inline_formatting("This is **bold** text");
120 assert_eq!(segments.len(), 3);
121 assert_eq!(segments[0].text, "This is ");
122 assert!(!segments[0].bold);
123 assert_eq!(segments[1].text, "bold");
124 assert!(segments[1].bold);
125 assert_eq!(segments[2].text, " text");
126 assert!(!segments[2].bold);
127 }
128
129 #[test]
130 fn test_parse_inline_formatting_italic() {
131 let segments = parse_inline_formatting("This is *italic* text");
132 assert_eq!(segments.len(), 3);
133 assert_eq!(segments[1].text, "italic");
134 assert!(segments[1].italic);
135 }
136
137 #[test]
138 fn test_parse_inline_formatting_code() {
139 let segments = parse_inline_formatting("Use `code` here");
140 assert_eq!(segments.len(), 3);
141 assert_eq!(segments[1].text, "code");
142 assert!(segments[1].code);
143 }
144
145 #[test]
146 fn test_parse_inline_formatting_mixed() {
147 let segments = parse_inline_formatting("**bold** and *italic*");
148 assert!(segments.iter().any(|s| s.bold && s.text == "bold"));
149 assert!(segments.iter().any(|s| s.italic && s.text == "italic"));
150 }
151}