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 }