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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-pptx-templater",
3
- "version": "1.0.12",
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",
@@ -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
- // Update the slide count and titles in docProps/app.xml to prevent repair mode issues
118
+ // Change this block to await the process completely
121
119
  if (zipManager.hasFile('docProps/app.xml')) {
122
- zipManager.addPendingPromise(
123
- zipManager.rawZip
124
- .file('docProps/app.xml')
125
- .async('text')
126
- .then(content => {
127
- const parser = new XMLParser()
128
- const appObj = parser.parse(content, 'app.xml')
129
- const properties = appObj.Properties
130
-
131
- if (properties) {
132
- // 1. Update Slides count
133
- properties.Slides = info.length
134
-
135
- // 2. Find old slide titles count and update HeadingPairs
136
- let oldSlideTitlesCount = 0
137
- const variants = properties.HeadingPairs?.['vt:vector']?.['vt:variant']
138
- if (Array.isArray(variants)) {
139
- for (let i = 0; i < variants.length; i++) {
140
- if (variants[i]['vt:lpstr'] === 'Slide Titles') {
141
- const countVar = variants[i + 1]
142
- if (countVar) {
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
- // 3. Update TitlesOfParts
152
- const titlesVector = properties.TitlesOfParts?.['vt:vector']
153
- if (titlesVector) {
154
- let lpstrs = titlesVector['vt:lpstr']
155
- if (lpstrs) {
156
- if (!Array.isArray(lpstrs)) lpstrs = [lpstrs]
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
- const declaration = '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
173
- const updatedXml = parser.build(appObj, declaration)
174
- zipManager.writeFile('docProps/app.xml', updatedXml)
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`)