1 /++
2 	Bare minimum support for reading Microsoft PowerPoint files.
3 
4 	History:
5 		Added February 19, 2025
6 +/
7 module arsd.pptx;
8 
9 // see ~/zip/ppt
10 
11 import arsd.core;
12 import arsd.zip;
13 import arsd.dom;
14 import arsd.color;
15 
16 /++
17 
18 +/
19 class PptxFile {
20 	private ZipFile zipFile;
21 	private XmlDocument document;
22 
23 	/++
24 
25 	+/
26 	this(FilePath file) {
27 		this.zipFile = new ZipFile(file);
28 
29 		load();
30 	}
31 
32 	/// ditto
33 	this(immutable(ubyte)[] rawData) {
34 		this.zipFile = new ZipFile(rawData);
35 
36 		load();
37 	}
38 
39 	/// public for now but idk forever.
40 	PptxSlide[] slides;
41 
42 	private string[string] contentTypes;
43 	private struct Relationship {
44 		string id;
45 		string type;
46 		string target;
47 	}
48 	private Relationship[string] relationships;
49 
50 	private void load() {
51 		loadXml("[Content_Types].xml", (document) {
52 			foreach(element; document.querySelectorAll("Override"))
53 				contentTypes[element.attrs.PartName] = element.attrs.ContentType;
54 		});
55 		loadXml("ppt/_rels/presentation.xml.rels", (document) {
56 			foreach(element; document.querySelectorAll("Relationship"))
57 				relationships[element.attrs.Id] = Relationship(element.attrs.Id, element.attrs.Type, element.attrs.Target);
58 		});
59 
60 		loadXml("ppt/presentation.xml", (document) {
61 			this.document = document;
62 
63 			foreach(element; document.querySelectorAll("p\\:sldIdLst p\\:sldId"))
64 				loadXml("ppt/" ~ relationships[element.getAttribute("r:id")].target, (document) {
65 					slides ~= new PptxSlide(this, document);
66 				});
67 		});
68 
69 		// then there's slide masters and layouts and idk what that is yet
70 	}
71 
72 	private void loadXml(string filename, scope void delegate(XmlDocument document) handler) {
73 		auto document = new XmlDocument(cast(string) zipFile.getContent(filename));
74 		handler(document);
75 	}
76 
77 }
78 
79 class PptxSlide {
80 	private PptxFile file;
81 	private XmlDocument document;
82 	private this(PptxFile file, XmlDocument document) {
83 		this.file = file;
84 		this.document = document;
85 	}
86 
87 	/++
88 	+/
89 	string toPlainText() {
90 		// FIXME: need to handle at least some of the layout
91 		return document.root.innerText;
92 	}
93 }