From 2cd6406b28a2e632e4232bdd1f4c3ad07d8ef819 Mon Sep 17 00:00:00 2001 From: Janos Erdos Date: Tue, 21 May 2024 21:35:22 +0200 Subject: [PATCH] fix: pptx rendering (#161) --- docs/DeveloperTroubleshooting.md | 57 ++++++++++++++++++ src/stencil/model.clj | 29 ++++++--- src/stencil/model/relations.clj | 22 ++++++- src/stencil/ooxml.clj | 8 ++- test-resources/presentation/presentation.pptx | Bin 0 -> 46166 bytes test/stencil/model_test.clj | 7 +++ 6 files changed, 111 insertions(+), 12 deletions(-) create mode 100644 test-resources/presentation/presentation.pptx diff --git a/docs/DeveloperTroubleshooting.md b/docs/DeveloperTroubleshooting.md index afa5d2e4..04b6c073 100644 --- a/docs/DeveloperTroubleshooting.md +++ b/docs/DeveloperTroubleshooting.md @@ -80,5 +80,62 @@ Problem: The zip entry paths mut not contain a `../` part. +-----------------+ | word/styles.xml | > shared across all +-----------------+ +``` + +## OOXML Presentation Model + +- Entry point is the same `.rels` file and main document is usually `ppt/_rels/presentation.xml` +- Main document references both `slide` and `slideMaster` and `theme` and `notesMaster` + - SlideMaster references `slideLayout` (and `theme`) pages + - Slide references `slideLayout` pages and `notesSlide` + - Theme page has no references + - SlideLayout references `slideMaster` pages. Note, there is a circular reference there! + - NotesSlide references `NotesMaster` + - NotesMaster references back to Theme. + +### SlideMaster + +> The master slide is the template upon which presentation slides are built. It specifies the shapes and objects as placeholders for content on presentation slides, as well as the formatting of the content within the placeholders. Of course the content and formatting specified on a master slide can be altered by layout slides and the presentation slides themselves, but absent such overrides, the master slide establishes the overall look and feel of the presentation. [Source](http://officeopenxml.com/prSlideMaster.php) +### SlideLayout + +> A slide layout is essentially a template design which can be applied to one or more slides, defining the default appearance and positioning of objects on the slide. It "sits" on top of the master slide, acting as an override to alter or supplement information provided on the master slide. When applied to a slide, all corresponding content within objects on the slide is mapped to the slide layout placeholders. [Source](http://officeopenxml.com/prSlideLayout.php) + + +``` + ┌─────────────┐ + │ _rels/.rels │ + └──────┬──────┘ + │ + ▼ + ┌─────────────────────┐ +┌───────────────────────────────┤/ppt/presentation.xml├───────────────────────────┐ +│ └─────────┬───────────┘ │ +│ │ │ +│ ▼ │ +│ ┌────────────────────────┐ │ +│ │/ppt/slides/slide{N}.xml│ │ +│ └─────┬──────────────────┘ │ +│ │ ▲ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌────────────────────────────────────┐ ┌─────────────────┐ │ +│ │/ppt/slideLayouts/slideLayout{N}.xml│ │notesSlide{N}.xml│ │ +│ └────────────────────────────────────┘ └─────┬───────────┘ │ +│ ▲ │ │ +│ │ │ │ +│ ▼ ▼ │ +│ ┌────────────────────────────────────┐ ┌──────────────────────────────────┐ │ +└─►│/ppt/slideMasters/slideMaster{N}.xml│ │/ppt/notesMasters/notesMaster1.xml│◄─┤ + └───────────────────────────────┬────┘ └─────┬────────────────────────────┘ │ + │ │ │ + │ ▼ │ + │ ┌────────────┐ │ + └──────►│theme{N}.xml│◄────────────────────────┤ + └────────────┘ │ + ▲ │ + │ │ + ┌───────┴────────────────────────────┐ │ + │/handoutMasters/handoutMaster{N}.xml│◄─┘ + └────────────────────────────────────┘ ``` diff --git a/src/stencil/model.clj b/src/stencil/model.clj index 5878d6b8..ebf7899b 100644 --- a/src/stencil/model.clj +++ b/src/stencil/model.clj @@ -24,6 +24,21 @@ (cleanup/process) (select-keys [:variables :dynamic? :executable :fragments])))) +(defn- ->submodel [dir f] + {::path (fs/unix-path (fs/unroll f)) + :source-file (file dir f) + :executable (->exec (file dir f)) + :relations (relations/->rels dir f)}) + +(defn- assoc-slide-layouts-notes [main-document dir] + (->> (for [hf (:headers+footers main-document) + :when (:relations hf) + target (relations/targets-by-type (:relations hf) + #{relations/rel-type-slide-layout relations/rel-type-notes-slide})] + (->submodel dir (file (fs/parent-file (file (::path hf))) target))) + (doall) + (assoc main-document ::slide-layouts))) + (defn load-template-model [dir, options-map] (assert (fs/exists? dir)) (assert (fs/directory? dir)) @@ -41,12 +56,9 @@ :executable (->exec (file dir main-document)) :relations main-document-rels :headers+footers (doall - (for [t (relations/targets-by-type main-document-rels relations/extra-relations) - :let [f (file (fs/parent-file (file main-document)) t)]] - {::path (fs/unix-path f) - :source-file (file dir f) - :executable (->exec (file dir f)) - :relations (relations/->rels dir f)}))} + (for [t (relations/targets-by-type main-document-rels relations/extra-relations)] + (->submodel dir (fs/unroll (file (fs/parent-file (file main-document)) t)))))} + (assoc-slide-layouts-notes dir) (style/assoc-style dir) (numbering/assoc-numbering dir))})) @@ -93,10 +105,11 @@ (assoc :result result)))))] (-> template-model (update-in [:main :headers+footers] (partial mapv evaluate)) + (update-in [:main ::slide-layouts] (partial mapv evaluate)) (update :main evaluate)))))))) (defn- model-seq [model] - (let [model-keys [:relations :headers+footers :main :style :content-types :fragments ::numbering :result]] + (let [model-keys [:relations :headers+footers :main :style :content-types :fragments ::numbering :result ::slide-layouts]] (tree-seq map? (fn [node] (flatten (keep node model-keys))) model))) @@ -161,7 +174,7 @@ ;; TODO: we could speed this up! (if-let [f (attr-mappers (:tag xml-tree))] (update-in xml-tree [:attrs ooxml/val] f) - (assoc xml-tree :content (mapv (partial xml-map-attrs attr-mappers) (:content xml-tree)))) + (assoc xml-tree :content (mapv (partial xml-map-attrs attr-mappers) (:content xml-tree)))) xml-tree)) ; And therefore: diff --git a/src/stencil/model/relations.clj b/src/stencil/model/relations.clj index 0835fa25..9e01d0f1 100644 --- a/src/stencil/model/relations.clj +++ b/src/stencil/model/relations.clj @@ -31,12 +31,28 @@ (def rel-type-header "http://schemas.openxmlformats.org/officeDocument/2006/relationships/header") +;; PPTX + (def rel-type-slide "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide") -(def extra-relations - #{rel-type-footer rel-type-header rel-type-slide}) +(def rel-type-slide-master + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideMaster") + +(def rel-type-slide-layout + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout") + +(def rel-type-theme + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/theme") +(def rel-type-notes-slide + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide") + +(def rel-type-notes-master + "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster") + +(def extra-relations + #{rel-type-footer rel-type-header rel-type-slide rel-type-slide-master rel-type-notes-master}) (defn- parse [rel-file] (with-open [reader (io/input-stream (file rel-file))] @@ -53,7 +69,7 @@ (defn ->rels [^java.io.File dir f] (let [rels-path (if f - (unix-path (file (fs/parent-file (file f)) "_rels" (str (.getName (file f)) ".rels"))) + (unix-path (fs/unroll (file (fs/parent-file (file f)) "_rels" (str (.getName (file f)) ".rels")))) (unix-path (file "_rels" ".rels"))) rels-file (file dir rels-path)] (when (fs/exists? rels-file) diff --git a/src/stencil/ooxml.clj b/src/stencil/ooxml.clj index 37126787..db0ce296 100644 --- a/src/stencil/ooxml.clj +++ b/src/stencil/ooxml.clj @@ -118,7 +118,13 @@ "http://schemas.microsoft.com/office/spreadsheetml/2015/revision2" "xr2" "http://schemas.microsoft.com/office/spreadsheetml/2016/revision3" "xr3" "http://schemas.microsoft.com/office/spreadsheetml/2016/revision6" "xr6" - "http://schemas.microsoft.com/office/spreadsheetml/2016/revision10" "xr10"}) + "http://schemas.microsoft.com/office/spreadsheetml/2016/revision10" "xr10" + ;additional aliases from PowerPoint + "http://schemas.openxmlformats.org/drawingml/2006/main" "a" + "http://schemas.openxmlformats.org/presentationml/2006/main" "p" + "http://schemas.microsoft.com/office/powerpoint/2010/main" "p14" + "http://schemas.microsoft.com/office/powerpoint/2012/main" "p15" + }) ;; drawing, binary large image or picture (def blip :xmlns.http%3A%2F%2Fschemas.openxmlformats.org%2Fdrawingml%2F2006%2Fmain/blip) diff --git a/test-resources/presentation/presentation.pptx b/test-resources/presentation/presentation.pptx new file mode 100644 index 0000000000000000000000000000000000000000..630c4527ea3a59082d5db422cda38340c1cc7286 GIT binary patch literal 46166 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 model (assoc-in [:content-types] :CT)