ppt_rs/generator/
notes_xml.rs1use crate::core::escape_xml;
4
5fn generate_field_guid(slide_num: usize) -> String {
8 format!("{{B0E4A5D7-2C3F-4A8B-9E1D-{:012X}}}", slide_num)
10}
11
12pub fn create_notes_xml(slide_num: usize, notes_text: &str) -> String {
14 let escaped_notes = escape_xml(notes_text);
15 let field_guid = generate_field_guid(slide_num);
16
17 format!(r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
18<p:notes 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">
19<p:cSld>
20<p:spTree>
21<p:nvGrpSpPr>
22<p:cNvPr id="1" name=""/>
23<p:cNvGrpSpPr/>
24<p:nvPr/>
25</p:nvGrpSpPr>
26<p:grpSpPr>
27<a:xfrm>
28<a:off x="0" y="0"/>
29<a:ext cx="0" cy="0"/>
30<a:chOff x="0" y="0"/>
31<a:chExt cx="0" cy="0"/>
32</a:xfrm>
33</p:grpSpPr>
34<p:sp>
35<p:nvSpPr>
36<p:cNvPr id="2" name="Slide Image Placeholder 1"/>
37<p:cNvSpPr>
38<a:spLocks noGrp="1" noRot="1" noChangeAspect="1"/>
39</p:cNvSpPr>
40<p:nvPr>
41<p:ph type="sldImg"/>
42</p:nvPr>
43</p:nvSpPr>
44<p:spPr/>
45</p:sp>
46<p:sp>
47<p:nvSpPr>
48<p:cNvPr id="3" name="Notes Placeholder 2"/>
49<p:cNvSpPr>
50<a:spLocks noGrp="1"/>
51</p:cNvSpPr>
52<p:nvPr>
53<p:ph type="body" idx="1"/>
54</p:nvPr>
55</p:nvSpPr>
56<p:spPr/>
57<p:txBody>
58<a:bodyPr/>
59<a:lstStyle/>
60<a:p>
61<a:r>
62<a:rPr lang="en-US" dirty="0"/>
63<a:t>{escaped_notes}</a:t>
64</a:r>
65</a:p>
66</p:txBody>
67</p:sp>
68<p:sp>
69<p:nvSpPr>
70<p:cNvPr id="4" name="Slide Number Placeholder 3"/>
71<p:cNvSpPr>
72<a:spLocks noGrp="1"/>
73</p:cNvSpPr>
74<p:nvPr>
75<p:ph type="sldNum" sz="quarter" idx="10"/>
76</p:nvPr>
77</p:nvSpPr>
78<p:spPr/>
79<p:txBody>
80<a:bodyPr/>
81<a:lstStyle/>
82<a:p>
83<a:fld id="{field_guid}" type="slidenum">
84<a:rPr lang="en-US"/>
85<a:t>{slide_num}</a:t>
86</a:fld>
87<a:endParaRPr lang="en-US"/>
88</a:p>
89</p:txBody>
90</p:sp>
91</p:spTree>
92</p:cSld>
93<p:clrMapOvr>
94<a:masterClrMapping/>
95</p:clrMapOvr>
96</p:notes>"#)
97}
98
99pub fn create_notes_rels_xml(slide_num: usize) -> String {
101 format!(r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
102<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
103<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide" Target="../slides/slide{slide_num}.xml"/>
104<Relationship Id="rId2" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster" Target="../notesMasters/notesMaster1.xml"/>
105</Relationships>"#)
106}
107
108pub fn create_notes_master_xml() -> String {
110 r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
111<p:notesMaster 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">
112<p:cSld>
113<p:spTree>
114<p:nvGrpSpPr>
115<p:cNvPr id="1" name=""/>
116<p:cNvGrpSpPr/>
117<p:nvPr/>
118</p:nvGrpSpPr>
119<p:grpSpPr>
120<a:xfrm>
121<a:off x="0" y="0"/>
122<a:ext cx="0" cy="0"/>
123<a:chOff x="0" y="0"/>
124<a:chExt cx="0" cy="0"/>
125</a:xfrm>
126</p:grpSpPr>
127<p:sp>
128<p:nvSpPr>
129<p:cNvPr id="2" name="Header Placeholder 1"/>
130<p:cNvSpPr>
131<a:spLocks noGrp="1"/>
132</p:cNvSpPr>
133<p:nvPr>
134<p:ph type="hdr" sz="quarter"/>
135</p:nvPr>
136</p:nvSpPr>
137<p:spPr>
138<a:xfrm>
139<a:off x="0" y="0"/>
140<a:ext cx="2971800" cy="458788"/>
141</a:xfrm>
142<a:prstGeom prst="rect">
143<a:avLst/>
144</a:prstGeom>
145</p:spPr>
146<p:txBody>
147<a:bodyPr vert="horz" lIns="91440" tIns="45720" rIns="91440" bIns="45720" rtlCol="0"/>
148<a:lstStyle>
149<a:lvl1pPr algn="l">
150<a:defRPr sz="1200"/>
151</a:lvl1pPr>
152</a:lstStyle>
153<a:p>
154<a:endParaRPr lang="en-US"/>
155</a:p>
156</p:txBody>
157</p:sp>
158<p:sp>
159<p:nvSpPr>
160<p:cNvPr id="3" name="Slide Image Placeholder 2"/>
161<p:cNvSpPr>
162<a:spLocks noGrp="1" noRot="1" noChangeAspect="1"/>
163</p:cNvSpPr>
164<p:nvPr>
165<p:ph type="sldImg" idx="2"/>
166</p:nvPr>
167</p:nvSpPr>
168<p:spPr>
169<a:xfrm>
170<a:off x="685800" y="1143000"/>
171<a:ext cx="5486400" cy="3086100"/>
172</a:xfrm>
173<a:prstGeom prst="rect">
174<a:avLst/>
175</a:prstGeom>
176<a:noFill/>
177<a:ln w="12700">
178<a:solidFill>
179<a:prstClr val="black"/>
180</a:solidFill>
181</a:ln>
182</p:spPr>
183<p:txBody>
184<a:bodyPr vert="horz" lIns="91440" tIns="45720" rIns="91440" bIns="45720" rtlCol="0" anchor="ctr"/>
185<a:lstStyle/>
186<a:p>
187<a:endParaRPr lang="en-US"/>
188</a:p>
189</p:txBody>
190</p:sp>
191<p:sp>
192<p:nvSpPr>
193<p:cNvPr id="4" name="Notes Placeholder 3"/>
194<p:cNvSpPr>
195<a:spLocks noGrp="1"/>
196</p:cNvSpPr>
197<p:nvPr>
198<p:ph type="body" sz="quarter" idx="3"/>
199</p:nvPr>
200</p:nvSpPr>
201<p:spPr>
202<a:xfrm>
203<a:off x="685800" y="4400550"/>
204<a:ext cx="5486400" cy="3600450"/>
205</a:xfrm>
206<a:prstGeom prst="rect">
207<a:avLst/>
208</a:prstGeom>
209</p:spPr>
210<p:txBody>
211<a:bodyPr vert="horz" lIns="91440" tIns="45720" rIns="91440" bIns="45720" rtlCol="0"/>
212<a:lstStyle/>
213<a:p>
214<a:pPr lvl="0"/>
215<a:r>
216<a:rPr lang="en-US"/>
217<a:t>Click to edit Master text styles</a:t>
218</a:r>
219</a:p>
220</p:txBody>
221</p:sp>
222</p:spTree>
223</p:cSld>
224<p:clrMap bg1="lt1" tx1="dk1" bg2="lt2" tx2="dk2" accent1="accent1" accent2="accent2" accent3="accent3" accent4="accent4" accent5="accent5" accent6="accent6" hlink="hlink" folHlink="folHlink"/>
225<p:notesStyle>
226<a:lvl1pPr marL="0" algn="l" defTabSz="914400" rtl="0" eaLnBrk="1" latinLnBrk="0" hangingPunct="1">
227<a:defRPr sz="1200" kern="1200">
228<a:solidFill>
229<a:schemeClr val="tx1"/>
230</a:solidFill>
231<a:latin typeface="+mn-lt"/>
232<a:ea typeface="+mn-ea"/>
233<a:cs typeface="+mn-cs"/>
234</a:defRPr>
235</a:lvl1pPr>
236</p:notesStyle>
237</p:notesMaster>"#.to_string()
238}
239
240pub fn create_notes_master_rels_xml() -> String {
242 r#"<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
243<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
244<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme" Target="../theme/theme1.xml"/>
245</Relationships>"#.to_string()
246}
247
248#[cfg(test)]
249mod tests {
250 use super::*;
251
252 #[test]
253 fn test_create_notes_xml() {
254 let xml = create_notes_xml(1, "These are my speaker notes");
255 assert!(xml.contains("p:notes"));
256 assert!(xml.contains("These are my speaker notes"));
257 assert!(xml.contains("Notes Placeholder"));
258 }
259
260 #[test]
261 fn test_create_notes_xml_escapes_special_chars() {
262 let xml = create_notes_xml(1, "Notes with <special> & \"chars\"");
263 assert!(xml.contains("<special>"));
264 assert!(xml.contains("&"));
265 assert!(xml.contains(""chars""));
266 }
267
268 #[test]
269 fn test_create_notes_rels_xml() {
270 let xml = create_notes_rels_xml(3);
271 assert!(xml.contains("slide3.xml"));
272 assert!(xml.contains("notesMaster1.xml"));
273 }
274
275 #[test]
276 fn test_create_notes_master_xml() {
277 let xml = create_notes_master_xml();
278 assert!(xml.contains("p:notesMaster"));
279 assert!(xml.contains("Notes Placeholder"));
280 }
281
282 #[test]
283 fn test_create_notes_master_rels_xml() {
284 let xml = create_notes_master_rels_xml();
285 assert!(xml.contains("theme1.xml"));
286 }
287}