node-pptx-templater 1.0.2 → 1.0.3

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.
Files changed (37) hide show
  1. package/README.md +336 -281
  2. package/package.json +1 -1
  3. package/src/cli/commands/build.js +30 -31
  4. package/src/cli/commands/debug.js +23 -23
  5. package/src/cli/commands/extract.js +21 -21
  6. package/src/cli/commands/inspect.js +23 -23
  7. package/src/cli/commands/validate.js +17 -17
  8. package/src/cli/index.js +39 -36
  9. package/src/core/OutputWriter.js +79 -78
  10. package/src/core/PPTXTemplater.js +856 -273
  11. package/src/core/TemplateEngine.js +67 -71
  12. package/src/core/ValidationEngine.js +246 -0
  13. package/src/index.js +30 -17
  14. package/src/managers/ChartManager.js +195 -70
  15. package/src/managers/ContentTypesManager.js +49 -45
  16. package/src/managers/HyperlinkManager.js +146 -142
  17. package/src/managers/ImageManager.js +336 -0
  18. package/src/managers/MediaManager.js +62 -81
  19. package/src/managers/RelationshipManager.js +99 -95
  20. package/src/managers/ShapeManager.js +340 -0
  21. package/src/managers/SlideManager.js +408 -311
  22. package/src/managers/TableManager.js +979 -262
  23. package/src/managers/TextManager.js +197 -0
  24. package/src/managers/ZipManager.js +69 -69
  25. package/src/managers/charts/ChartCacheGenerator.js +75 -58
  26. package/src/managers/charts/ChartParser.js +9 -13
  27. package/src/managers/charts/ChartRelationshipManager.js +12 -10
  28. package/src/managers/charts/ChartWorkbookUpdater.js +59 -56
  29. package/src/parsers/XMLParser.js +47 -50
  30. package/src/templates/blankPptx.js +3 -2
  31. package/src/templates/slideTemplate.js +28 -34
  32. package/src/utils/contentTypesHelper.js +40 -54
  33. package/src/utils/errors.js +18 -18
  34. package/src/utils/idUtils.js +16 -14
  35. package/src/utils/logger.js +18 -16
  36. package/src/utils/relationshipUtils.js +19 -20
  37. package/src/utils/xmlUtils.js +26 -26
@@ -20,11 +20,8 @@
20
20
  * mc: — Markup Compatibility
21
21
  */
22
22
 
23
- const { XMLParser: FastXMLParser, XMLBuilder } = require('fast-xml-parser');
24
- const { createLogger } = require('../utils/logger.js');
25
- const { PPTXError } = require('../utils/errors.js');
26
-
27
- const logger = createLogger('XMLParser');
23
+ const { XMLParser: FastXMLParser, XMLBuilder } = require('fast-xml-parser')
24
+ const { PPTXError } = require('../utils/errors.js')
28
25
 
29
26
  /**
30
27
  * Parser configuration for fast-xml-parser.
@@ -67,10 +64,10 @@ const PARSER_OPTIONS = {
67
64
  'Default',
68
65
  'p14:sldId',
69
66
  'p14:section',
70
- ];
71
- return alwaysArrayPaths.some(path => jpath.endsWith(path) || name === path.split('.').pop());
67
+ ]
68
+ return alwaysArrayPaths.some(path => jpath.endsWith(path) || name === path.split('.').pop())
72
69
  },
73
- };
70
+ }
74
71
 
75
72
  /**
76
73
  * Builder configuration for XMLBuilder.
@@ -85,7 +82,7 @@ const BUILDER_OPTIONS = {
85
82
  suppressEmptyNode: false,
86
83
  format: false, // No extra whitespace — PPTX is sensitive to whitespace in some cases
87
84
  processEntities: true,
88
- };
85
+ }
89
86
 
90
87
  /**
91
88
  * @class XMLParser
@@ -96,17 +93,17 @@ class XMLParser {
96
93
  * @private
97
94
  * @type {FastXMLParser}
98
95
  */
99
- #parser;
96
+ #parser
100
97
 
101
98
  /**
102
99
  * @private
103
100
  * @type {XMLBuilder}
104
101
  */
105
- #builder;
102
+ #builder
106
103
 
107
104
  constructor() {
108
- this.#parser = new FastXMLParser(PARSER_OPTIONS);
109
- this.#builder = new XMLBuilder(BUILDER_OPTIONS);
105
+ this.#parser = new FastXMLParser(PARSER_OPTIONS)
106
+ this.#builder = new XMLBuilder(BUILDER_OPTIONS)
110
107
  }
111
108
 
112
109
  /**
@@ -123,13 +120,13 @@ class XMLParser {
123
120
  */
124
121
  parse(xmlString, context = '') {
125
122
  if (!xmlString || typeof xmlString !== 'string') {
126
- throw new PPTXError(`Invalid XML input${context ? ` (${context})` : ''}`);
123
+ throw new PPTXError(`Invalid XML input${context ? ` (${context})` : ''}`)
127
124
  }
128
125
 
129
126
  try {
130
- return this.#parser.parse(xmlString);
127
+ return this.#parser.parse(xmlString)
131
128
  } catch (err) {
132
- throw new PPTXError(`XML parse error${context ? ` in ${context}` : ''}: ${err.message}`, err);
129
+ throw new PPTXError(`XML parse error${context ? ` in ${context}` : ''}: ${err.message}`, err)
133
130
  }
134
131
  }
135
132
 
@@ -145,10 +142,10 @@ class XMLParser {
145
142
  */
146
143
  build(obj, xmlDeclaration = '') {
147
144
  try {
148
- const xml = this.#builder.build(obj);
149
- return xmlDeclaration ? `${xmlDeclaration}\n${xml}` : xml;
145
+ const xml = this.#builder.build(obj)
146
+ return xmlDeclaration ? `${xmlDeclaration}\n${xml}` : xml
150
147
  } catch (err) {
151
- throw new PPTXError(`XML build error: ${err.message}`, err);
148
+ throw new PPTXError(`XML build error: ${err.message}`, err)
152
149
  }
153
150
  }
154
151
 
@@ -159,8 +156,8 @@ class XMLParser {
159
156
  * @returns {string} Declaration line or empty string.
160
157
  */
161
158
  extractDeclaration(xmlString) {
162
- const match = xmlString.match(/^<\?xml[^>]+\?>/);
163
- return match ? match[0] : '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>';
159
+ const match = xmlString.match(/^<\?xml[^>]+\?>/)
160
+ return match ? match[0] : '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
164
161
  }
165
162
 
166
163
  /**
@@ -171,7 +168,7 @@ class XMLParser {
171
168
  * @returns {Object} Deep clone.
172
169
  */
173
170
  deepClone(obj) {
174
- return JSON.parse(JSON.stringify(obj));
171
+ return JSON.parse(JSON.stringify(obj))
175
172
  }
176
173
 
177
174
  /**
@@ -186,25 +183,25 @@ class XMLParser {
186
183
  * const runs = parser.findAll(slideObj, 'p:cSld.p:spTree.p:sp.p:txBody.a:p.a:r');
187
184
  */
188
185
  findAll(obj, path) {
189
- const keys = path.split('.');
190
- let current = [obj];
186
+ const keys = path.split('.')
187
+ let current = [obj]
191
188
 
192
189
  for (const key of keys) {
193
- const next = [];
190
+ const next = []
194
191
  for (const node of current) {
195
192
  if (node && typeof node === 'object') {
196
- const val = node[key];
193
+ const val = node[key]
197
194
  if (Array.isArray(val)) {
198
- next.push(...val);
195
+ next.push(...val)
199
196
  } else if (val !== undefined) {
200
- next.push(val);
197
+ next.push(val)
201
198
  }
202
199
  }
203
200
  }
204
- current = next;
201
+ current = next
205
202
  }
206
203
 
207
- return current;
204
+ return current
208
205
  }
209
206
 
210
207
  /**
@@ -215,7 +212,7 @@ class XMLParser {
215
212
  * @returns {*} First matching node or undefined.
216
213
  */
217
214
  getNode(obj, path) {
218
- return this.findAll(obj, path)[0];
215
+ return this.findAll(obj, path)[0]
219
216
  }
220
217
 
221
218
  /**
@@ -227,18 +224,18 @@ class XMLParser {
227
224
  * @param {*} value - Value to set.
228
225
  */
229
226
  setNode(obj, path, value) {
230
- const keys = path.split('.');
231
- let current = obj;
227
+ const keys = path.split('.')
228
+ let current = obj
232
229
 
233
230
  for (let i = 0; i < keys.length - 1; i++) {
234
- const key = keys[i];
231
+ const key = keys[i]
235
232
  if (!current[key] || typeof current[key] !== 'object') {
236
- current[key] = {};
233
+ current[key] = {}
237
234
  }
238
- current = Array.isArray(current[key]) ? current[key][0] : current[key];
235
+ current = Array.isArray(current[key]) ? current[key][0] : current[key]
239
236
  }
240
237
 
241
- current[keys[keys.length - 1]] = value;
238
+ current[keys[keys.length - 1]] = value
242
239
  }
243
240
 
244
241
  /**
@@ -252,9 +249,9 @@ class XMLParser {
252
249
  * @returns {string} Modified XML string.
253
250
  */
254
251
  replaceInXml(xmlString, search, replace, all = true) {
255
- const escaped = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
256
- const flags = all ? 'g' : '';
257
- return xmlString.replace(new RegExp(escaped, flags), replace);
252
+ const escaped = search.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
253
+ const flags = all ? 'g' : ''
254
+ return xmlString.replace(new RegExp(escaped, flags), replace)
258
255
  }
259
256
 
260
257
  /**
@@ -265,13 +262,13 @@ class XMLParser {
265
262
  * @returns {string[]} Array of text strings found in the slide.
266
263
  */
267
264
  extractTextContent(xmlString) {
268
- const texts = [];
269
- const textPattern = /<a:t>([^<]*)<\/a:t>/g;
270
- let match;
265
+ const texts = []
266
+ const textPattern = /<a:t>([^<]*)<\/a:t>/g
267
+ let match
271
268
  while ((match = textPattern.exec(xmlString)) !== null) {
272
- if (match[1].trim()) texts.push(match[1]);
269
+ if (match[1].trim()) texts.push(match[1])
273
270
  }
274
- return texts;
271
+ return texts
275
272
  }
276
273
 
277
274
  /**
@@ -282,14 +279,14 @@ class XMLParser {
282
279
  */
283
280
  validate(xmlString) {
284
281
  try {
285
- this.parse(xmlString);
286
- return { valid: true, error: null };
282
+ this.parse(xmlString)
283
+ return { valid: true, error: null }
287
284
  } catch (err) {
288
- return { valid: false, error: err.message };
285
+ return { valid: false, error: err.message }
289
286
  }
290
287
  }
291
288
  }
292
289
 
293
290
  module.exports = {
294
- XMLParser
295
- };
291
+ XMLParser,
292
+ }