node-pptx-templater 1.0.1 → 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 +6 -6
  3. package/src/cli/commands/build.js +32 -31
  4. package/src/cli/commands/debug.js +25 -24
  5. package/src/cli/commands/extract.js +23 -21
  6. package/src/cli/commands/inspect.js +25 -23
  7. package/src/cli/commands/validate.js +19 -17
  8. package/src/cli/index.js +45 -43
  9. package/src/core/OutputWriter.js +81 -78
  10. package/src/core/PPTXTemplater.js +859 -274
  11. package/src/core/TemplateEngine.js +69 -71
  12. package/src/core/ValidationEngine.js +246 -0
  13. package/src/index.js +51 -15
  14. package/src/managers/ChartManager.js +197 -70
  15. package/src/managers/ContentTypesManager.js +51 -45
  16. package/src/managers/HyperlinkManager.js +148 -142
  17. package/src/managers/ImageManager.js +336 -0
  18. package/src/managers/MediaManager.js +64 -81
  19. package/src/managers/RelationshipManager.js +102 -96
  20. package/src/managers/ShapeManager.js +340 -0
  21. package/src/managers/SlideManager.js +410 -311
  22. package/src/managers/TableManager.js +981 -262
  23. package/src/managers/TextManager.js +197 -0
  24. package/src/managers/ZipManager.js +71 -69
  25. package/src/managers/charts/ChartCacheGenerator.js +77 -58
  26. package/src/managers/charts/ChartParser.js +11 -13
  27. package/src/managers/charts/ChartRelationshipManager.js +14 -10
  28. package/src/managers/charts/ChartWorkbookUpdater.js +61 -56
  29. package/src/parsers/XMLParser.js +50 -49
  30. package/src/templates/blankPptx.js +3 -1
  31. package/src/templates/slideTemplate.js +31 -32
  32. package/src/utils/contentTypesHelper.js +41 -53
  33. package/src/utils/errors.js +33 -23
  34. package/src/utils/idUtils.js +23 -15
  35. package/src/utils/logger.js +21 -15
  36. package/src/utils/relationshipUtils.js +28 -22
  37. package/src/utils/xmlUtils.js +37 -29
@@ -26,15 +26,15 @@
26
26
  * This "text normalization" approach correctly handles fragmented placeholders.
27
27
  */
28
28
 
29
- import { createLogger } from '../utils/logger.js';
29
+ const { createLogger } = require('../utils/logger.js')
30
30
 
31
- const logger = createLogger('TemplateEngine');
31
+ const logger = createLogger('TemplateEngine')
32
32
 
33
33
  /**
34
34
  * Default placeholder pattern: {{key}}
35
35
  * Can be overridden per-call.
36
36
  */
37
- const DEFAULT_PLACEHOLDER_PATTERN = /\{\{([^{}]+)\}\}/g;
37
+ const DEFAULT_PLACEHOLDER_PATTERN = /\{\{([^{}]+)\}\}/g
38
38
 
39
39
  /**
40
40
  * @class TemplateEngine
@@ -42,15 +42,15 @@ const DEFAULT_PLACEHOLDER_PATTERN = /\{\{([^{}]+)\}\}/g;
42
42
  *
43
43
  * Implements the text-normalization strategy to handle fragmented placeholders.
44
44
  */
45
- export class TemplateEngine {
45
+ class TemplateEngine {
46
46
  /** @private @type {XMLParser} */
47
- #xmlParser;
47
+ #xmlParser
48
48
 
49
49
  /**
50
50
  * @param {XMLParser} xmlParser
51
51
  */
52
52
  constructor(xmlParser) {
53
- this.#xmlParser = xmlParser;
53
+ this.#xmlParser = xmlParser
54
54
  }
55
55
 
56
56
  /**
@@ -68,28 +68,28 @@ export class TemplateEngine {
68
68
  * '{{date}}': '2026-01-01'
69
69
  * });
70
70
  */
71
- replaceTextInXml(slideXml, replacements, pattern = DEFAULT_PLACEHOLDER_PATTERN) {
71
+ replaceTextInXml(slideXml, replacements) {
72
72
  if (!replacements || Object.keys(replacements).length === 0) {
73
- return slideXml;
73
+ return slideXml
74
74
  }
75
75
 
76
- logger.debug(`Replacing ${Object.keys(replacements).length} placeholder(s)`);
76
+ logger.debug(`Replacing ${Object.keys(replacements).length} placeholder(s)`)
77
77
 
78
78
  // Step 1: Process paragraph by paragraph to handle fragmented runs
79
- let updated = this.#processParagraphs(slideXml, replacements);
79
+ let updated = this.#processParagraphs(slideXml, replacements)
80
80
 
81
81
  // Step 2: Simple direct replacement for any remaining unfragmented placeholders
82
82
  for (const [placeholder, value] of Object.entries(replacements)) {
83
- const escaped = this.#escapeXml(String(value));
84
- const placeholderEscaped = this.#escapeXml(placeholder);
83
+ const escaped = this.#escapeXml(String(value))
84
+ const placeholderEscaped = this.#escapeXml(placeholder)
85
85
 
86
86
  // Replace the XML-escaped form (e.g., {{name}} as {{name}})
87
- updated = updated.split(placeholderEscaped).join(escaped);
87
+ updated = updated.split(placeholderEscaped).join(escaped)
88
88
  // Replace the plain form (in case it's not escaped in the XML)
89
- updated = updated.split(placeholder).join(escaped);
89
+ updated = updated.split(placeholder).join(escaped)
90
90
  }
91
91
 
92
- return updated;
92
+ return updated
93
93
  }
94
94
 
95
95
  /**
@@ -103,30 +103,28 @@ export class TemplateEngine {
103
103
  */
104
104
  #processParagraphs(slideXml, replacements) {
105
105
  // Find all <a:p>...</a:p> paragraphs
106
- let updated = slideXml;
107
- let offset = 0;
106
+ let updated = slideXml
107
+ let offset = 0
108
108
 
109
- const paragraphPattern = /<a:p>([\s\S]*?)<\/a:p>/g;
110
- let match;
109
+ const paragraphPattern = /<a:p>([\s\S]*?)<\/a:p>/g
110
+ let match
111
111
 
112
112
  while ((match = paragraphPattern.exec(slideXml)) !== null) {
113
- const paragraphXml = match[0];
114
- const processedParagraph = this.#processParagraph(paragraphXml, replacements);
113
+ const paragraphXml = match[0]
114
+ const processedParagraph = this.#processParagraph(paragraphXml, replacements)
115
115
 
116
116
  if (processedParagraph !== paragraphXml) {
117
- // Replace in the updated string (adjust for offset changes)
118
- const start = updated.indexOf(paragraphXml, match.index + offset - (match.index));
119
-
120
117
  // More reliable: replace from the beginning of the current search area
121
- updated = updated.substring(0, match.index + offset) +
118
+ updated =
119
+ updated.substring(0, match.index + offset) +
122
120
  processedParagraph +
123
- updated.substring(match.index + offset + paragraphXml.length);
121
+ updated.substring(match.index + offset + paragraphXml.length)
124
122
 
125
- offset += processedParagraph.length - paragraphXml.length;
123
+ offset += processedParagraph.length - paragraphXml.length
126
124
  }
127
125
  }
128
126
 
129
- return updated;
127
+ return updated
130
128
  }
131
129
 
132
130
  /**
@@ -139,32 +137,32 @@ export class TemplateEngine {
139
137
  */
140
138
  #processParagraph(paragraphXml, replacements) {
141
139
  // Extract all text runs from this paragraph
142
- const runs = this.#extractRuns(paragraphXml);
140
+ const runs = this.#extractRuns(paragraphXml)
143
141
 
144
- if (runs.length === 0) return paragraphXml;
142
+ if (runs.length === 0) return paragraphXml
145
143
 
146
144
  // Combine text from all runs
147
- const combinedText = runs.map(r => r.text).join('');
145
+ const combinedText = runs.map(r => r.text).join('')
148
146
 
149
147
  // Check if any placeholder appears in the combined text
150
- let hasPlaceholder = false;
148
+ let hasPlaceholder = false
151
149
  for (const placeholder of Object.keys(replacements)) {
152
150
  if (combinedText.includes(placeholder)) {
153
- hasPlaceholder = true;
154
- break;
151
+ hasPlaceholder = true
152
+ break
155
153
  }
156
154
  }
157
155
 
158
- if (!hasPlaceholder) return paragraphXml;
156
+ if (!hasPlaceholder) return paragraphXml
159
157
 
160
158
  // Perform replacement on combined text
161
- let replacedText = combinedText;
159
+ let replacedText = combinedText
162
160
  for (const [placeholder, value] of Object.entries(replacements)) {
163
- replacedText = replacedText.split(placeholder).join(String(value));
161
+ replacedText = replacedText.split(placeholder).join(String(value))
164
162
  }
165
163
 
166
164
  // Rebuild the paragraph: merge all runs into a single run using first run's format
167
- return this.#mergeRunsWithText(paragraphXml, runs, replacedText);
165
+ return this.#mergeRunsWithText(paragraphXml, runs, replacedText)
168
166
  }
169
167
 
170
168
  /**
@@ -176,25 +174,25 @@ export class TemplateEngine {
176
174
  * @returns {Array<{xml: string, text: string, start: number, end: number}>}
177
175
  */
178
176
  #extractRuns(paragraphXml) {
179
- const runs = [];
180
- const runPattern = /(<a:r(?:\s[^>]*)?>)([\s\S]*?)(<\/a:r>)/g;
181
- let match;
177
+ const runs = []
178
+ const runPattern = /(<a:r(?:\s[^>]*)?>)([\s\S]*?)(<\/a:r>)/g
179
+ let match
182
180
 
183
181
  while ((match = runPattern.exec(paragraphXml)) !== null) {
184
- const runXml = match[0];
182
+ const runXml = match[0]
185
183
  // Extract text from <a:t>...</a:t> within this run
186
- const tMatch = /<a:t>([\s\S]*?)<\/a:t>/.exec(runXml);
187
- const text = tMatch ? this.#unescapeXml(tMatch[1]) : '';
184
+ const tMatch = /<a:t>([\s\S]*?)<\/a:t>/.exec(runXml)
185
+ const text = tMatch ? this.#unescapeXml(tMatch[1]) : ''
188
186
 
189
187
  runs.push({
190
188
  xml: runXml,
191
189
  text,
192
190
  start: match.index,
193
191
  end: match.index + runXml.length,
194
- });
192
+ })
195
193
  }
196
194
 
197
- return runs;
195
+ return runs
198
196
  }
199
197
 
200
198
  /**
@@ -208,25 +206,23 @@ export class TemplateEngine {
208
206
  * @returns {string} Updated paragraph XML.
209
207
  */
210
208
  #mergeRunsWithText(paragraphXml, runs, newText) {
211
- if (runs.length === 0) return paragraphXml;
209
+ if (runs.length === 0) return paragraphXml
212
210
 
213
211
  // Use the first run as the format template
214
- const firstRun = runs[0];
212
+ const firstRun = runs[0]
215
213
 
216
214
  // Build the replacement run: first run's format + new text
217
- const mergedRunXml = this.#setRunText(firstRun.xml, this.#escapeXml(newText));
215
+ const mergedRunXml = this.#setRunText(firstRun.xml, this.#escapeXml(newText))
218
216
 
219
217
  // Build new paragraph:
220
218
  // Keep everything before first run, insert merged run, remove the rest,
221
219
  // keep everything after last run
222
- const firstRunStart = firstRun.start;
223
- const lastRunEnd = runs[runs.length - 1].end;
220
+ const firstRunStart = firstRun.start
221
+ const lastRunEnd = runs[runs.length - 1].end
224
222
 
225
223
  return (
226
- paragraphXml.substring(0, firstRunStart) +
227
- mergedRunXml +
228
- paragraphXml.substring(lastRunEnd)
229
- );
224
+ paragraphXml.substring(0, firstRunStart) + mergedRunXml + paragraphXml.substring(lastRunEnd)
225
+ )
230
226
  }
231
227
 
232
228
  /**
@@ -238,12 +234,12 @@ export class TemplateEngine {
238
234
  * @returns {string} Updated run XML.
239
235
  */
240
236
  #setRunText(runXml, text) {
241
- const tPattern = /(<a:t>)([\s\S]*?)(<\/a:t>)/;
237
+ const tPattern = /(<a:t>)([\s\S]*?)(<\/a:t>)/
242
238
  if (tPattern.test(runXml)) {
243
- return runXml.replace(tPattern, `$1${text}$3`);
239
+ return runXml.replace(tPattern, `$1${text}$3`)
244
240
  }
245
241
  // If no <a:t>, add one before </a:r>
246
- return runXml.replace('</a:r>', `<a:t>${text}</a:t></a:r>`);
242
+ return runXml.replace('</a:r>', `<a:t>${text}</a:t></a:r>`)
247
243
  }
248
244
 
249
245
  /**
@@ -254,7 +250,7 @@ export class TemplateEngine {
254
250
  * @returns {boolean}
255
251
  */
256
252
  containsPlaceholders(text, replacements) {
257
- return Object.keys(replacements).some(p => text.includes(p));
253
+ return Object.keys(replacements).some(p => text.includes(p))
258
254
  }
259
255
 
260
256
  /**
@@ -269,24 +265,24 @@ export class TemplateEngine {
269
265
  * // → ['{{title}}', '{{date}}', '{{company}}']
270
266
  */
271
267
  extractPlaceholders(xml, pattern = DEFAULT_PLACEHOLDER_PATTERN) {
272
- const placeholders = new Set();
273
- const textPattern = /<a:t>([\s\S]*?)<\/a:t>/g;
274
- let match;
268
+ const placeholders = new Set()
269
+ const textPattern = /<a:t>([\s\S]*?)<\/a:t>/g
270
+ let match
275
271
 
276
272
  // Extract text content first, then find placeholders
277
- const allText = [];
273
+ const allText = []
278
274
  while ((match = textPattern.exec(xml)) !== null) {
279
- allText.push(match[1]);
275
+ allText.push(match[1])
280
276
  }
281
277
 
282
- const combined = allText.join('');
283
- const plPattern = new RegExp(pattern.source, 'g');
284
- let plMatch;
278
+ const combined = allText.join('')
279
+ const plPattern = new RegExp(pattern.source, 'g')
280
+ let plMatch
285
281
  while ((plMatch = plPattern.exec(combined)) !== null) {
286
- placeholders.add(plMatch[0]);
282
+ placeholders.add(plMatch[0])
287
283
  }
288
284
 
289
- return Array.from(placeholders);
285
+ return Array.from(placeholders)
290
286
  }
291
287
 
292
288
  /**
@@ -301,7 +297,7 @@ export class TemplateEngine {
301
297
  .replace(/</g, '&lt;')
302
298
  .replace(/>/g, '&gt;')
303
299
  .replace(/"/g, '&quot;')
304
- .replace(/'/g, '&apos;');
300
+ .replace(/'/g, '&apos;')
305
301
  }
306
302
 
307
303
  /**
@@ -316,6 +312,8 @@ export class TemplateEngine {
316
312
  .replace(/&lt;/g, '<')
317
313
  .replace(/&gt;/g, '>')
318
314
  .replace(/&quot;/g, '"')
319
- .replace(/&apos;/g, "'");
315
+ .replace(/&apos;/g, "'")
320
316
  }
321
317
  }
318
+
319
+ module.exports = { TemplateEngine }
@@ -0,0 +1,246 @@
1
+ /**
2
+ * @fileoverview ValidationEngine - Complete validation and checking engine for PowerPoint presentations.
3
+ */
4
+
5
+ /**
6
+ * @class ValidationEngine
7
+ * @description Runs audits and verification checks on PPTX files.
8
+ */
9
+ class ValidationEngine {
10
+ /**
11
+ * Validates the entire presentation.
12
+ *
13
+ * @param {PPTXTemplater} ppt - The presentation templater instance.
14
+ * @returns {Promise<Object>} Structured report.
15
+ */
16
+ static async validatePresentation(ppt) {
17
+ const errors = []
18
+ const warnings = []
19
+
20
+ // 1. Validate slides and references
21
+ const slides = ppt.slideManager.getAllSlideInfo()
22
+ for (const slide of slides) {
23
+ // Validate slide relationships
24
+ const relResult = this.validateRelationships(ppt, slide.zipPath)
25
+ errors.push(...relResult.errors.map(e => `Slide ${slide.index} relationship error: ${e}`))
26
+ warnings.push(
27
+ ...relResult.warnings.map(w => `Slide ${slide.index} relationship warning: ${w}`)
28
+ )
29
+
30
+ // Validate slide XML and elements
31
+ const slideResult = await this.validateSlide(ppt, slide.index)
32
+ errors.push(...slideResult.errors)
33
+ warnings.push(...slideResult.warnings)
34
+ }
35
+
36
+ // 2. Validate presentation level relationships
37
+ const presRelResult = this.validateRelationships(ppt, 'ppt/presentation.xml')
38
+ errors.push(...presRelResult.errors.map(e => `Presentation relationship error: ${e}`))
39
+ warnings.push(...presRelResult.warnings.map(w => `Presentation relationship warning: ${w}`))
40
+
41
+ return {
42
+ valid: errors.length === 0,
43
+ errors,
44
+ warnings,
45
+ }
46
+ }
47
+
48
+ /**
49
+ * Validates a single slide's XML and elements (like tables, shapes, charts).
50
+ *
51
+ * @param {PPTXTemplater} ppt
52
+ * @param {number} slideIndex
53
+ * @returns {Promise<Object>}
54
+ */
55
+ static async validateSlide(ppt, slideIndex) {
56
+ const errors = []
57
+ const warnings = []
58
+
59
+ try {
60
+ const slideXml = await ppt.slideManager.getSlideXmlAsync(slideIndex)
61
+
62
+ // Verify well-formed XML
63
+ const xmlCheck = ppt.xmlParser.validate(slideXml)
64
+ if (!xmlCheck.valid) {
65
+ errors.push(`Slide ${slideIndex} XML syntax error: ${xmlCheck.error}`)
66
+ return { valid: false, errors, warnings }
67
+ }
68
+
69
+ // Verify tables on the slide
70
+ const tables = ppt.tableManager.inspectTables(slideIndex, ppt.slideManager)
71
+ for (const table of tables) {
72
+ const tableResult = await this.validateTable(ppt, slideIndex, table.id)
73
+ errors.push(
74
+ ...tableResult.errors.map(e => `Slide ${slideIndex} Table "${table.name}": ${e}`)
75
+ )
76
+ warnings.push(
77
+ ...tableResult.warnings.map(w => `Slide ${slideIndex} Table "${table.name}": ${w}`)
78
+ )
79
+ }
80
+
81
+ // Verify charts on the slide
82
+ const charts = ppt.chartManager.getChartsInSlide(
83
+ slideIndex,
84
+ ppt.slideManager,
85
+ ppt.relationshipManager
86
+ )
87
+ for (const chart of charts) {
88
+ if (!ppt.zipManager.hasFile(chart.zipPath)) {
89
+ errors.push(
90
+ `Slide ${slideIndex} referenced chart file does not exist at ${chart.zipPath}`
91
+ )
92
+ }
93
+ }
94
+
95
+ // Verify image references on the slide
96
+ const images = ppt.imageManager.getImages(
97
+ slideIndex,
98
+ ppt.slideManager,
99
+ ppt.relationshipManager
100
+ )
101
+ for (const image of images) {
102
+ if (image.targetPath && !ppt.zipManager.hasFile(image.targetPath)) {
103
+ errors.push(
104
+ `Slide ${slideIndex} referenced image file does not exist at ${image.targetPath}`
105
+ )
106
+ }
107
+ }
108
+ } catch (err) {
109
+ errors.push(`Slide ${slideIndex} validation error: ${err.message}`)
110
+ }
111
+
112
+ return {
113
+ valid: errors.length === 0,
114
+ errors,
115
+ warnings,
116
+ }
117
+ }
118
+
119
+ /**
120
+ * Validates a table's XML and OpenXML conformity.
121
+ *
122
+ * @param {PPTXTemplater} ppt
123
+ * @param {number} slideIndex
124
+ * @param {string} tableId
125
+ * @returns {Promise<Object>}
126
+ */
127
+ static async validateTable(ppt, slideIndex, tableId) {
128
+ const errors = []
129
+ const warnings = []
130
+
131
+ try {
132
+ const slideXml = await ppt.slideManager.getSlideXmlAsync(slideIndex)
133
+ const slideObj = ppt.xmlParser.parse(slideXml, `slide${slideIndex}.xml`)
134
+
135
+ const spTree = slideObj?.['p:sld']?.['p:cSld']?.['p:spTree']
136
+ if (!spTree) {
137
+ errors.push('Slide shape tree not found')
138
+ return { valid: false, errors, warnings }
139
+ }
140
+
141
+ let frames = spTree['p:graphicFrame'] || []
142
+ if (!Array.isArray(frames)) frames = [frames]
143
+
144
+ let tbl = null
145
+ for (const frame of frames) {
146
+ const t = frame?.['a:graphic']?.['a:graphicData']?.['a:tbl']
147
+ if (!t) continue
148
+ const cNvPr = frame?.['p:nvGraphicFramePr']?.['p:cNvPr']
149
+ if (cNvPr && (cNvPr['@_name'] === tableId || String(cNvPr['@_id']) === tableId)) {
150
+ tbl = t
151
+ break
152
+ }
153
+ }
154
+
155
+ if (!tbl) {
156
+ errors.push(`Table "${tableId}" not found in slide object`)
157
+ return { valid: false, errors, warnings }
158
+ }
159
+
160
+ // Check cols against gridcols
161
+ const cols = tbl['a:tblGrid']?.['a:gridCol'] || []
162
+ const trs = tbl['a:tr'] || []
163
+
164
+ if (cols.length === 0) {
165
+ errors.push('Table column definitions (tblGrid) are missing')
166
+ }
167
+
168
+ // Check rowIds duplicate values
169
+ const rowIds = new Set()
170
+ trs.forEach((tr, rIdx) => {
171
+ const tcs = tr['a:tc'] || []
172
+ if (tcs.length !== cols.length) {
173
+ warnings.push(
174
+ `Row ${rIdx} cell count (${tcs.length}) does not match grid columns count (${cols.length})`
175
+ )
176
+ }
177
+
178
+ // Check for rowId
179
+ const ext = tr['a:extLst']?.['a:ext']
180
+ const exts = Array.isArray(ext) ? ext : [ext]
181
+ for (const e of exts) {
182
+ if (e?.['a16:rowId']) {
183
+ const val = e['a16:rowId']['@_val']
184
+ if (val) {
185
+ if (rowIds.has(val)) {
186
+ errors.push(`Duplicate a16:rowId "${val}" found at row index ${rIdx}`)
187
+ }
188
+ rowIds.add(val)
189
+ }
190
+ }
191
+ }
192
+ })
193
+ } catch (err) {
194
+ errors.push(`Table validation error: ${err.message}`)
195
+ }
196
+
197
+ return {
198
+ valid: errors.length === 0,
199
+ errors,
200
+ warnings,
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Validates relationship mappings for a specific part.
206
+ *
207
+ * @param {PPTXTemplater} ppt
208
+ * @param {string} partPath
209
+ * @returns {Object}
210
+ */
211
+ static validateRelationships(ppt, partPath) {
212
+ const errors = []
213
+ const warnings = []
214
+
215
+ const relsPath = ppt.relationshipManager.getRelsPath(partPath)
216
+ if (!ppt.zipManager.hasFile(relsPath)) {
217
+ warnings.push(`Relationship file missing at ${relsPath}`)
218
+ return { valid: true, errors, warnings }
219
+ }
220
+
221
+ const rels = ppt.relationshipManager.getRelationships(partPath)
222
+ const relIds = new Set()
223
+
224
+ for (const rel of rels) {
225
+ if (relIds.has(rel.id)) {
226
+ errors.push(`Duplicate relationship ID "${rel.id}" inside ${relsPath}`)
227
+ }
228
+ relIds.add(rel.id)
229
+
230
+ if (rel.targetMode !== 'External') {
231
+ const resolved = ppt.relationshipManager.resolveTarget(partPath, rel.target)
232
+ if (!ppt.zipManager.hasFile(resolved)) {
233
+ errors.push(`Relationship ${rel.id} points to non-existent file: ${resolved}`)
234
+ }
235
+ }
236
+ }
237
+
238
+ return {
239
+ valid: errors.length === 0,
240
+ errors,
241
+ warnings,
242
+ }
243
+ }
244
+ }
245
+
246
+ module.exports = { ValidationEngine }
package/src/index.js CHANGED
@@ -24,20 +24,56 @@
24
24
  * └─────────────────────────────────────────────────────────────┘
25
25
  */
26
26
 
27
- export { PPTXTemplater } from './core/PPTXTemplater.js';
28
- export { ZipManager } from './managers/ZipManager.js';
29
- export { XMLParser } from './parsers/XMLParser.js';
30
- export { SlideManager } from './managers/SlideManager.js';
31
- export { ChartManager } from './managers/ChartManager.js';
32
- export { TableManager } from './managers/TableManager.js';
33
- export { HyperlinkManager } from './managers/HyperlinkManager.js';
34
- export { MediaManager } from './managers/MediaManager.js';
35
- export { RelationshipManager } from './managers/RelationshipManager.js';
36
- export { OutputWriter } from './core/OutputWriter.js';
37
- export { TemplateEngine } from './core/TemplateEngine.js';
27
+ const { PPTXTemplater } = require('./core/PPTXTemplater.js')
28
+ const { ZipManager } = require('./managers/ZipManager.js')
29
+ const { XMLParser } = require('./parsers/XMLParser.js')
30
+ const { SlideManager } = require('./managers/SlideManager.js')
31
+ const { ChartManager } = require('./managers/ChartManager.js')
32
+ const { TableManager } = require('./managers/TableManager.js')
33
+ const { ShapeManager } = require('./managers/ShapeManager.js')
34
+ const { ImageManager } = require('./managers/ImageManager.js')
35
+ const { TextManager } = require('./managers/TextManager.js')
36
+ const { HyperlinkManager } = require('./managers/HyperlinkManager.js')
37
+ const { MediaManager } = require('./managers/MediaManager.js')
38
+ const { RelationshipManager } = require('./managers/RelationshipManager.js')
39
+ const { OutputWriter } = require('./core/OutputWriter.js')
40
+ const { TemplateEngine } = require('./core/TemplateEngine.js')
41
+ const { ValidationEngine } = require('./core/ValidationEngine.js')
38
42
 
39
43
  // Utility exports
40
- export { generateRelationshipId, parseRelationshipId } from './utils/relationshipUtils.js';
41
- export { validateXML, repairXML } from './utils/xmlUtils.js';
42
- export { createLogger } from './utils/logger.js';
43
- export { PPTXError, SlideNotFoundError, ChartNotFoundError, TableNotFoundError } from './utils/errors.js';
44
+ const { generateRelationshipId, parseRelationshipId } = require('./utils/relationshipUtils.js')
45
+ const { validateXML, repairXML } = require('./utils/xmlUtils.js')
46
+ const { createLogger } = require('./utils/logger.js')
47
+ const {
48
+ PPTXError,
49
+ SlideNotFoundError,
50
+ ChartNotFoundError,
51
+ TableNotFoundError,
52
+ } = require('./utils/errors.js')
53
+
54
+ module.exports = {
55
+ PPTXTemplater,
56
+ ZipManager,
57
+ XMLParser,
58
+ SlideManager,
59
+ ChartManager,
60
+ TableManager,
61
+ ShapeManager,
62
+ ImageManager,
63
+ TextManager,
64
+ HyperlinkManager,
65
+ MediaManager,
66
+ RelationshipManager,
67
+ OutputWriter,
68
+ TemplateEngine,
69
+ ValidationEngine,
70
+ generateRelationshipId,
71
+ parseRelationshipId,
72
+ validateXML,
73
+ repairXML,
74
+ createLogger,
75
+ PPTXError,
76
+ SlideNotFoundError,
77
+ ChartNotFoundError,
78
+ TableNotFoundError,
79
+ }