node-pptx-templater 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/OutputWriter.js +44 -52
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "node-pptx-templater",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.13",
|
|
4
4
|
"description": "High-performance, low-level PowerPoint (PPTX) OpenXML template engine for Node.js. Dynamically replace text, insert images, update charts (with Excel workbook data caching), and merge table cells without PowerPoint corruption or Repair Mode prompts.",
|
|
5
5
|
"main": "./src/index.js",
|
|
6
6
|
"type": "commonjs",
|
package/src/core/OutputWriter.js
CHANGED
|
@@ -107,8 +107,6 @@ class OutputWriter {
|
|
|
107
107
|
* @returns {Promise<void>}
|
|
108
108
|
*/
|
|
109
109
|
async #flushAllSlides(slideManager, zipManager) {
|
|
110
|
-
// SlideManager already writes to zipManager via setSlideXml,
|
|
111
|
-
// so this is mostly a no-op with a validation step.
|
|
112
110
|
const info = slideManager.getAllSlideInfo()
|
|
113
111
|
|
|
114
112
|
for (const slide of info) {
|
|
@@ -117,64 +115,58 @@ class OutputWriter {
|
|
|
117
115
|
}
|
|
118
116
|
}
|
|
119
117
|
|
|
120
|
-
//
|
|
118
|
+
// Change this block to await the process completely
|
|
121
119
|
if (zipManager.hasFile('docProps/app.xml')) {
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
if (
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
oldSlideTitlesCount = parseInt(countVar['vt:i4'], 10) || 0
|
|
144
|
-
countVar['vt:i4'] = info.length
|
|
145
|
-
}
|
|
146
|
-
break
|
|
120
|
+
// AWAIT this process entirely before exiting the function!
|
|
121
|
+
await zipManager.rawZip
|
|
122
|
+
.file('docProps/app.xml')
|
|
123
|
+
.async('text')
|
|
124
|
+
.then(content => {
|
|
125
|
+
const parser = new XMLParser()
|
|
126
|
+
const appObj = parser.parse(content, 'app.xml')
|
|
127
|
+
const properties = appObj.Properties
|
|
128
|
+
|
|
129
|
+
if (properties) {
|
|
130
|
+
properties.Slides = info.length
|
|
131
|
+
|
|
132
|
+
let oldSlideTitlesCount = 0
|
|
133
|
+
const variants = properties.HeadingPairs?.['vt:vector']?.['vt:variant']
|
|
134
|
+
if (Array.isArray(variants)) {
|
|
135
|
+
for (let i = 0; i < variants.length; i++) {
|
|
136
|
+
if (variants[i]['vt:lpstr'] === 'Slide Titles') {
|
|
137
|
+
const countVar = variants[i + 1]
|
|
138
|
+
if (countVar) {
|
|
139
|
+
oldSlideTitlesCount = parseInt(countVar['vt:i4'], 10) || 0
|
|
140
|
+
countVar['vt:i4'] = info.length
|
|
147
141
|
}
|
|
142
|
+
break
|
|
148
143
|
}
|
|
149
144
|
}
|
|
145
|
+
}
|
|
150
146
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (lpstrs)
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// Remove the old slide titles (which are at the end)
|
|
159
|
-
if (oldSlideTitlesCount > 0 && lpstrs.length >= oldSlideTitlesCount) {
|
|
160
|
-
lpstrs = lpstrs.slice(0, lpstrs.length - oldSlideTitlesCount)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
// Append new slide titles
|
|
164
|
-
const newSlideTitles = info.map(slide => slide.title || `Slide ${slide.index}`)
|
|
165
|
-
lpstrs.push(...newSlideTitles)
|
|
166
|
-
|
|
167
|
-
titlesVector['vt:lpstr'] = lpstrs
|
|
168
|
-
titlesVector['@_size'] = String(lpstrs.length)
|
|
147
|
+
const titlesVector = properties.TitlesOfParts?.['vt:vector']
|
|
148
|
+
if (titlesVector) {
|
|
149
|
+
let lpstrs = titlesVector['vt:lpstr']
|
|
150
|
+
if (lpstrs) {
|
|
151
|
+
if (!Array.isArray(lpstrs)) lpstrs = [lpstrs]
|
|
152
|
+
if (oldSlideTitlesCount > 0 && lpstrs.length >= oldSlideTitlesCount) {
|
|
153
|
+
lpstrs = lpstrs.slice(0, lpstrs.length - oldSlideTitlesCount)
|
|
169
154
|
}
|
|
170
|
-
|
|
155
|
+
const newSlideTitles = info.map(slide => slide.title || `Slide ${slide.index}`)
|
|
156
|
+
lpstrs.push(...newSlideTitles)
|
|
171
157
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
158
|
+
titlesVector['vt:lpstr'] = lpstrs
|
|
159
|
+
titlesVector['@_size'] = String(lpstrs.length)
|
|
160
|
+
}
|
|
175
161
|
}
|
|
176
|
-
|
|
177
|
-
|
|
162
|
+
|
|
163
|
+
const declaration = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
|
164
|
+
const updatedXml = parser.build(appObj, declaration)
|
|
165
|
+
|
|
166
|
+
// Writing it safely here now that the function block is strictly sequential
|
|
167
|
+
zipManager.writeFile('docProps/app.xml', updatedXml)
|
|
168
|
+
}
|
|
169
|
+
})
|
|
178
170
|
}
|
|
179
171
|
|
|
180
172
|
logger.debug(`Flushed ${info.length} slide(s) to ZIP`)
|