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
package/package.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "node-pptx-templater",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Low-level PowerPoint OpenXML template engine for Node.js — generate and edit PPTX files directly through XML manipulation without relying on PowerPoint generation libraries.",
5
5
  "main": "./src/index.js",
6
- "type": "module",
6
+ "type": "commonjs",
7
7
  "exports": {
8
8
  ".": {
9
- "import": "./src/index.js"
9
+ "require": "./src/index.js"
10
10
  }
11
11
  },
12
12
  "bin": {
@@ -65,8 +65,8 @@
65
65
  "jszip": "^3.10.1",
66
66
  "fs-extra": "^11.2.0",
67
67
  "commander": "^12.0.0",
68
- "chalk": "^5.3.0",
69
- "ora": "^8.0.1"
68
+ "chalk": "^4.1.2",
69
+ "ora": "^5.4.1"
70
70
  },
71
71
  "devDependencies": {
72
72
  "vitest": "^1.6.0",
@@ -80,4 +80,4 @@
80
80
  "LICENSE",
81
81
  "CHANGELOG.md"
82
82
  ]
83
- }
83
+ }
@@ -2,11 +2,11 @@
2
2
  * @fileoverview `build` CLI command — builds a PPTX from a template + JSON data.
3
3
  */
4
4
 
5
- import chalk from 'chalk';
6
- import ora from 'ora';
7
- import { readFileSync } from 'fs';
8
- import { resolve } from 'path';
9
- import { PPTXTemplater } from '../../index.js';
5
+ const chalk = require('chalk')
6
+ const ora = require('ora')
7
+ const { readFileSync } = require('fs')
8
+ const { resolve } = require('path')
9
+ const { PPTXTemplater } = require('../../index.js')
10
10
 
11
11
  /**
12
12
  * Executes the `build` CLI command.
@@ -15,65 +15,66 @@ import { PPTXTemplater } from '../../index.js';
15
15
  * @param {string} outputPath - Path for the generated PPTX.
16
16
  * @param {Object} opts - CLI options.
17
17
  */
18
- export async function buildCommand(templatePath, outputPath, opts) {
19
- const spinner = ora(`Loading template: ${templatePath}`).start();
18
+ async function buildCommand(templatePath, outputPath, opts) {
19
+ const spinner = ora(`Loading template: ${templatePath}`).start()
20
20
 
21
21
  try {
22
22
  // Load the template
23
- const ppt = await PPTXTemplater.load(resolve(templatePath));
24
- spinner.succeed(`Loaded template (${ppt.slideCount} slides)`);
23
+ const ppt = await PPTXTemplater.load(resolve(templatePath))
24
+ spinner.succeed(`Loaded template (${ppt.slideCount} slides)`)
25
25
 
26
26
  // Apply slide filter if provided
27
27
  if (opts.slide) {
28
- const slideNumbers = opts.slide.split(',').map(n => parseInt(n.trim(), 10));
29
- ppt.useSlide(...slideNumbers);
30
- console.log(chalk.cyan(` → Using slides: ${slideNumbers.join(', ')}`));
28
+ const slideNumbers = opts.slide.split(',').map(n => parseInt(n.trim(), 10))
29
+ ppt.useSlide(...slideNumbers)
30
+ console.log(chalk.cyan(` → Using slides: ${slideNumbers.join(', ')}`))
31
31
  }
32
32
 
33
33
  // Apply data from JSON file if provided
34
34
  if (opts.data) {
35
- spinner.start(`Loading data: ${opts.data}`);
36
- const data = JSON.parse(readFileSync(resolve(opts.data), 'utf-8'));
35
+ spinner.start(`Loading data: ${opts.data}`)
36
+ const data = JSON.parse(readFileSync(resolve(opts.data), 'utf-8'))
37
37
 
38
38
  // Apply text replacements
39
39
  if (data.text) {
40
- ppt.replaceText(data.text);
41
- console.log(chalk.cyan(` → Replaced ${Object.keys(data.text).length} text placeholder(s)`));
40
+ ppt.replaceText(data.text)
41
+ console.log(chalk.cyan(` → Replaced ${Object.keys(data.text).length} text placeholder(s)`))
42
42
  }
43
43
 
44
44
  // Apply chart updates
45
45
  if (data.charts) {
46
46
  for (const [chartId, chartData] of Object.entries(data.charts)) {
47
- ppt.updateChart(chartId, chartData);
48
- console.log(chalk.cyan(` → Updated chart: ${chartId}`));
47
+ ppt.updateChart(chartId, chartData)
48
+ console.log(chalk.cyan(` → Updated chart: ${chartId}`))
49
49
  }
50
50
  }
51
51
 
52
52
  // Apply table updates
53
53
  if (data.tables) {
54
54
  for (const [tableId, tableData] of Object.entries(data.tables)) {
55
- ppt.updateTable(tableId, tableData);
56
- console.log(chalk.cyan(` → Updated table: ${tableId}`));
55
+ ppt.updateTable(tableId, tableData)
56
+ console.log(chalk.cyan(` → Updated table: ${tableId}`))
57
57
  }
58
58
  }
59
59
 
60
- spinner.succeed('Data applied');
60
+ spinner.succeed('Data applied')
61
61
  }
62
62
 
63
63
  // Save output
64
- spinner.start(`Saving to: ${outputPath}`);
65
- await ppt.saveToFile(resolve(outputPath));
66
- spinner.succeed(chalk.green(`✓ Saved: ${outputPath}`));
67
-
68
- console.log(chalk.dim(`\n Slides: ${ppt.slideCount}`));
69
- console.log(chalk.dim(` Template: ${templatePath}`));
70
- console.log(chalk.dim(` Output: ${outputPath}\n`));
64
+ spinner.start(`Saving to: ${outputPath}`)
65
+ await ppt.saveToFile(resolve(outputPath))
66
+ spinner.succeed(chalk.green(`✓ Saved: ${outputPath}`))
71
67
 
68
+ console.log(chalk.dim(`\n Slides: ${ppt.slideCount}`))
69
+ console.log(chalk.dim(` Template: ${templatePath}`))
70
+ console.log(chalk.dim(` Output: ${outputPath}\n`))
72
71
  } catch (err) {
73
- spinner.fail(chalk.red(`Build failed: ${err.message}`));
72
+ spinner.fail(chalk.red(`Build failed: ${err.message}`))
74
73
  if (process.env.PPTX_LOG_LEVEL === 'debug') {
75
- console.error(err.stack);
74
+ console.error(err.stack)
76
75
  }
77
- process.exit(1);
76
+ process.exit(1)
78
77
  }
79
78
  }
79
+
80
+ module.exports = { buildCommand }
@@ -1,46 +1,47 @@
1
1
  /**
2
2
  * @fileoverview `debug` CLI command — diagnoses and repairs corrupted PPTX files.
3
3
  */
4
- import chalk from 'chalk';
5
- import ora from 'ora';
6
- import { resolve } from 'path';
7
- import { repairXML } from '../../utils/xmlUtils.js';
8
- import { PPTXTemplater } from '../../index.js';
4
+ const chalk = require('chalk')
5
+ const ora = require('ora')
6
+ const { resolve } = require('path')
7
+ const { PPTXTemplater } = require('../../index.js')
9
8
 
10
- export async function debugCommand(filePath, opts) {
11
- const spinner = ora(`Loading PPTX for debug: ${filePath}`).start();
9
+ async function debugCommand(filePath, opts) {
10
+ const spinner = ora(`Loading PPTX for debug: ${filePath}`).start()
12
11
 
13
12
  try {
14
- const ppt = await PPTXTemplater.load(resolve(filePath));
15
- spinner.succeed('Loaded successfully');
13
+ const ppt = await PPTXTemplater.load(resolve(filePath))
14
+ spinner.succeed('Loaded successfully')
16
15
 
17
- const result = ppt.validate();
16
+ const result = ppt.validate()
18
17
 
19
- console.log(chalk.bold.cyan('\n═══ Debug Report ═══\n'));
20
- console.log(chalk.bold('Validation:'));
18
+ console.log(chalk.bold.cyan('\n═══ Debug Report ═══\n'))
19
+ console.log(chalk.bold('Validation:'))
21
20
 
22
21
  if (result.valid) {
23
- console.log(chalk.green(' ✓ Structure is valid'));
22
+ console.log(chalk.green(' ✓ Structure is valid'))
24
23
  } else {
25
- console.log(chalk.red(` ✗ ${result.errors.length} error(s) found`));
26
- result.errors.forEach(e => console.log(chalk.red(` • ${e}`)));
24
+ console.log(chalk.red(` ✗ ${result.errors.length} error(s) found`))
25
+ result.errors.forEach(e => console.log(chalk.red(` • ${e}`)))
27
26
  }
28
27
 
29
28
  if (result.warnings.length > 0) {
30
- console.log(chalk.yellow(`\n ${result.warnings.length} warning(s):`));
31
- result.warnings.forEach(w => console.log(chalk.yellow(` • ${w}`)));
29
+ console.log(chalk.yellow(`\n ${result.warnings.length} warning(s):`))
30
+ result.warnings.forEach(w => console.log(chalk.yellow(` • ${w}`)))
32
31
  }
33
32
 
34
33
  if (opts.fix && opts.out) {
35
- spinner.start('Attempting repairs...');
36
- await ppt.saveToFile(resolve(opts.out));
37
- spinner.succeed(chalk.green(`✓ Repaired PPTX saved to: ${opts.out}`));
34
+ spinner.start('Attempting repairs...')
35
+ await ppt.saveToFile(resolve(opts.out))
36
+ spinner.succeed(chalk.green(`✓ Repaired PPTX saved to: ${opts.out}`))
38
37
  }
39
38
 
40
- console.log('');
39
+ console.log('')
41
40
  } catch (err) {
42
- spinner.fail(chalk.red(`Debug failed: ${err.message}`));
43
- if (process.env.PPTX_LOG_LEVEL === 'debug') console.error(err.stack);
44
- process.exit(1);
41
+ spinner.fail(chalk.red(`Debug failed: ${err.message}`))
42
+ if (process.env.PPTX_LOG_LEVEL === 'debug') console.error(err.stack)
43
+ process.exit(1)
45
44
  }
46
45
  }
46
+
47
+ module.exports = { debugCommand }
@@ -1,42 +1,44 @@
1
1
  /**
2
2
  * @fileoverview `extract` CLI command — extracts XML parts from a PPTX.
3
3
  */
4
- import chalk from 'chalk';
5
- import { resolve } from 'path';
6
- import { writeFileSync } from 'fs';
7
- import { PPTXTemplater } from '../../index.js';
4
+ const chalk = require('chalk')
5
+ const { resolve } = require('path')
6
+ const { writeFileSync } = require('fs')
7
+ const { PPTXTemplater } = require('../../index.js')
8
8
 
9
- export async function extractCommand(filePath, opts) {
9
+ async function extractCommand(filePath, opts) {
10
10
  try {
11
- const ppt = await PPTXTemplater.load(resolve(filePath));
11
+ const ppt = await PPTXTemplater.load(resolve(filePath))
12
12
 
13
13
  if (opts.slide) {
14
- const slideNum = parseInt(opts.slide, 10);
14
+ const slideNum = parseInt(opts.slide, 10)
15
15
  // Access internal zip via the engine's buffer
16
- const buffer = await ppt.toBuffer();
17
- const JSZip = (await import('jszip')).default;
18
- const zip = await JSZip.loadAsync(buffer);
19
- const slideFile = zip.file(`ppt/slides/slide${slideNum}.xml`);
16
+ const buffer = await ppt.toBuffer()
17
+ const JSZip = require('jszip')
18
+ const zip = await JSZip.loadAsync(buffer)
19
+ const slideFile = zip.file(`ppt/slides/slide${slideNum}.xml`)
20
20
 
21
21
  if (!slideFile) {
22
- console.error(chalk.red(`Slide ${slideNum} not found`));
23
- process.exit(1);
22
+ console.error(chalk.red(`Slide ${slideNum} not found`))
23
+ process.exit(1)
24
24
  }
25
25
 
26
- const xml = await slideFile.async('text');
26
+ const xml = await slideFile.async('text')
27
27
 
28
28
  if (opts.out) {
29
- writeFileSync(resolve(opts.out), xml, 'utf-8');
30
- console.log(chalk.green(`✓ Extracted slide ${slideNum} to ${opts.out}`));
29
+ writeFileSync(resolve(opts.out), xml, 'utf-8')
30
+ console.log(chalk.green(`✓ Extracted slide ${slideNum} to ${opts.out}`))
31
31
  } else {
32
- console.log(xml);
32
+ console.log(xml)
33
33
  }
34
34
  } else {
35
- console.log(chalk.yellow('Specify --slide <number> to extract'));
36
- process.exit(1);
35
+ console.log(chalk.yellow('Specify --slide <number> to extract'))
36
+ process.exit(1)
37
37
  }
38
38
  } catch (err) {
39
- console.error(chalk.red(`Extract failed: ${err.message}`));
40
- process.exit(1);
39
+ console.error(chalk.red(`Extract failed: ${err.message}`))
40
+ process.exit(1)
41
41
  }
42
42
  }
43
+
44
+ module.exports = { extractCommand }
@@ -1,39 +1,41 @@
1
1
  /**
2
2
  * @fileoverview `inspect` CLI command — detailed PPTX structure inspection.
3
3
  */
4
- import chalk from 'chalk';
5
- import ora from 'ora';
6
- import { resolve } from 'path';
7
- import { PPTXTemplater } from '../../index.js';
4
+ const chalk = require('chalk')
5
+ const ora = require('ora')
6
+ const { resolve } = require('path')
7
+ const { PPTXTemplater } = require('../../index.js')
8
8
 
9
- export async function inspectCommand(filePath, opts) {
10
- const showAll = opts.all;
11
- const spinner = ora(`Inspecting: ${filePath}`).start();
9
+ async function inspectCommand(filePath, opts) {
10
+ const showAll = opts.all
11
+ const spinner = ora(`Inspecting: ${filePath}`).start()
12
12
 
13
13
  try {
14
- const ppt = await PPTXTemplater.load(resolve(filePath));
15
- const info = ppt.getInfo();
16
- spinner.stop();
14
+ const ppt = await PPTXTemplater.load(resolve(filePath))
15
+ const info = ppt.getInfo()
16
+ spinner.stop()
17
17
 
18
- console.log(chalk.bold.cyan('\n═══ PPTX Inspection Report ═══\n'));
19
- console.log(chalk.bold('General:'));
20
- console.log(` Title: ${info.title || chalk.dim('(none)')}`);
21
- console.log(` Author: ${info.author || chalk.dim('(none)')}`);
22
- console.log(` Created: ${info.created || chalk.dim('(unknown)')}`);
23
- console.log(` Slides: ${chalk.cyan(info.slideCount)}`);
24
- console.log(` Media: ${chalk.cyan(info.mediaCount)} files`);
18
+ console.log(chalk.bold.cyan('\n═══ PPTX Inspection Report ═══\n'))
19
+ console.log(chalk.bold('General:'))
20
+ console.log(` Title: ${info.title || chalk.dim('(none)')}`)
21
+ console.log(` Author: ${info.author || chalk.dim('(none)')}`)
22
+ console.log(` Created: ${info.created || chalk.dim('(unknown)')}`)
23
+ console.log(` Slides: ${chalk.cyan(info.slideCount)}`)
24
+ console.log(` Media: ${chalk.cyan(info.mediaCount)} files`)
25
25
 
26
26
  if (opts.slides || showAll) {
27
- console.log(chalk.bold('\nSlides:'));
27
+ console.log(chalk.bold('\nSlides:'))
28
28
  for (const slide of info.slides) {
29
- const tags = slide.tags.length > 0 ? chalk.dim(` [${slide.tags.join(', ')}]`) : '';
30
- console.log(` ${chalk.cyan(slide.index.toString().padStart(2))}. ${slide.zipPath}${tags}`);
29
+ const tags = slide.tags.length > 0 ? chalk.dim(` [${slide.tags.join(', ')}]`) : ''
30
+ console.log(` ${chalk.cyan(slide.index.toString().padStart(2))}. ${slide.zipPath}${tags}`)
31
31
  }
32
32
  }
33
33
 
34
- console.log('');
34
+ console.log('')
35
35
  } catch (err) {
36
- spinner.fail(chalk.red(`Inspect failed: ${err.message}`));
37
- process.exit(1);
36
+ spinner.fail(chalk.red(`Inspect failed: ${err.message}`))
37
+ process.exit(1)
38
38
  }
39
39
  }
40
+
41
+ module.exports = { inspectCommand }
@@ -1,36 +1,38 @@
1
1
  /**
2
2
  * @fileoverview `validate` CLI command.
3
3
  */
4
- import chalk from 'chalk';
5
- import ora from 'ora';
6
- import { resolve } from 'path';
7
- import { PPTXTemplater } from '../../index.js';
4
+ const chalk = require('chalk')
5
+ const ora = require('ora')
6
+ const { resolve } = require('path')
7
+ const { PPTXTemplater } = require('../../index.js')
8
8
 
9
- export async function validateCommand(filePath, opts) {
10
- const spinner = ora(`Validating: ${filePath}`).start();
9
+ async function validateCommand(filePath, opts) {
10
+ const spinner = ora(`Validating: ${filePath}`).start()
11
11
  try {
12
- const ppt = await PPTXTemplater.load(resolve(filePath));
13
- const result = ppt.validate();
14
- spinner.stop();
12
+ const ppt = await PPTXTemplater.load(resolve(filePath))
13
+ const result = ppt.validate()
14
+ spinner.stop()
15
15
 
16
16
  if (result.valid && result.warnings.length === 0) {
17
- console.log(chalk.green(`\n✓ Valid PPTX (${ppt.slideCount} slides)\n`));
17
+ console.log(chalk.green(`\n✓ Valid PPTX (${ppt.slideCount} slides)\n`))
18
18
  } else {
19
19
  if (result.errors.length > 0) {
20
- console.log(chalk.red(`\n✗ Validation errors (${result.errors.length}):\n`));
21
- result.errors.forEach(e => console.log(chalk.red(` • ${e}`)));
20
+ console.log(chalk.red(`\n✗ Validation errors (${result.errors.length}):\n`))
21
+ result.errors.forEach(e => console.log(chalk.red(` • ${e}`)))
22
22
  }
23
23
  if (result.warnings.length > 0) {
24
- console.log(chalk.yellow(`\n⚠ Warnings (${result.warnings.length}):\n`));
25
- result.warnings.forEach(w => console.log(chalk.yellow(` • ${w}`)));
24
+ console.log(chalk.yellow(`\n⚠ Warnings (${result.warnings.length}):\n`))
25
+ result.warnings.forEach(w => console.log(chalk.yellow(` • ${w}`)))
26
26
  }
27
27
  }
28
28
 
29
29
  if (!result.valid || (opts.strict && result.warnings.length > 0)) {
30
- process.exit(1);
30
+ process.exit(1)
31
31
  }
32
32
  } catch (err) {
33
- spinner.fail(chalk.red(`Validation failed: ${err.message}`));
34
- process.exit(1);
33
+ spinner.fail(chalk.red(`Validation failed: ${err.message}`))
34
+ process.exit(1)
35
35
  }
36
36
  }
37
+
38
+ module.exports = { validateCommand }
package/src/cli/index.js CHANGED
@@ -18,45 +18,43 @@
18
18
  * node-pptx-templater --help
19
19
  */
20
20
 
21
- import { Command } from 'commander';
22
- import chalk from 'chalk';
23
- import ora from 'ora';
24
- import { readFileSync } from 'fs';
25
- import { resolve, dirname } from 'path';
26
- import { fileURLToPath } from 'url';
27
- import { PPTXTemplater } from '../index.js';
28
- import { buildCommand } from './commands/build.js';
29
- import { validateCommand } from './commands/validate.js';
30
- import { inspectCommand } from './commands/inspect.js';
31
- import { extractCommand } from './commands/extract.js';
32
- import { debugCommand } from './commands/debug.js';
33
-
34
- const __dirname = dirname(fileURLToPath(import.meta.url));
21
+ const { Command } = require('commander')
22
+ const chalk = require('chalk')
23
+ const { readFileSync } = require('fs')
24
+ const { resolve } = require('path')
25
+ const { buildCommand } = require('./commands/build.js')
26
+ const { validateCommand } = require('./commands/validate.js')
27
+ const { inspectCommand } = require('./commands/inspect.js')
28
+ const { extractCommand } = require('./commands/extract.js')
29
+ const { debugCommand } = require('./commands/debug.js')
35
30
 
36
31
  // Read version from package.json
37
- const pkg = JSON.parse(
38
- readFileSync(resolve(__dirname, '../../package.json'), 'utf-8')
39
- );
32
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '../../package.json'), 'utf-8'))
40
33
 
41
34
  /**
42
35
  * CLI banner displayed on startup.
43
36
  */
44
37
  function printBanner() {
45
- console.log(chalk.bold.cyan(`
38
+ console.log(
39
+ chalk.bold.cyan(`
46
40
  ╔═══════════════════════════════════════════════╗
47
41
  ║ node-pptx-templater v${pkg.version.padEnd(17)}║
48
42
  ║ Low-level OpenXML PowerPoint template engine ║
49
43
  ╚═══════════════════════════════════════════════╝
50
- `));
44
+ `)
45
+ )
51
46
  }
52
47
 
53
- const program = new Command();
48
+ const program = new Command()
54
49
 
55
50
  program
56
51
  .name('node-pptx-templater')
57
52
  .description('Low-level PowerPoint OpenXML template engine for Node.js')
58
53
  .version(pkg.version, '-v, --version', 'Display version number')
59
- .addHelpText('before', chalk.bold.cyan('\nnode-pptx-templater — PowerPoint XML manipulation engine\n'));
54
+ .addHelpText(
55
+ 'before',
56
+ chalk.bold.cyan('\nnode-pptx-templater — PowerPoint XML manipulation engine\n')
57
+ )
60
58
 
61
59
  // ─── build command ─────────────────────────────────────────────────────────
62
60
  program
@@ -66,9 +64,9 @@ program
66
64
  .option('-s, --slide <numbers>', 'Comma-separated slide numbers to include (e.g., 1,3,5)')
67
65
  .option('--no-banner', 'Suppress the banner')
68
66
  .action(async (template, output, opts) => {
69
- if (!opts.noBanner) printBanner();
70
- await buildCommand(template, output, opts);
71
- });
67
+ if (!opts.noBanner) printBanner()
68
+ await buildCommand(template, output, opts)
69
+ })
72
70
 
73
71
  // ─── validate command ───────────────────────────────────────────────────────
74
72
  program
@@ -76,9 +74,9 @@ program
76
74
  .description('Validate the structure of a PPTX file')
77
75
  .option('--strict', 'Exit with error code on warnings too')
78
76
  .action(async (file, opts) => {
79
- printBanner();
80
- await validateCommand(file, opts);
81
- });
77
+ printBanner()
78
+ await validateCommand(file, opts)
79
+ })
82
80
 
83
81
  // ─── inspect command ────────────────────────────────────────────────────────
84
82
  program
@@ -91,9 +89,9 @@ program
91
89
  .option('--rels', 'Show relationship tree')
92
90
  .option('--all', 'Show everything')
93
91
  .action(async (file, opts) => {
94
- printBanner();
95
- await inspectCommand(file, opts);
96
- });
92
+ printBanner()
93
+ await inspectCommand(file, opts)
94
+ })
97
95
 
98
96
  // ─── extract command ────────────────────────────────────────────────────────
99
97
  program
@@ -104,8 +102,8 @@ program
104
102
  .option('--chart <name>', 'Extract chart XML by name')
105
103
  .option('--rels', 'Extract relationship files')
106
104
  .action(async (file, opts) => {
107
- await extractCommand(file, opts);
108
- });
105
+ await extractCommand(file, opts)
106
+ })
109
107
 
110
108
  // ─── debug command ──────────────────────────────────────────────────────────
111
109
  program
@@ -114,19 +112,23 @@ program
114
112
  .option('--fix', 'Attempt automatic repairs')
115
113
  .option('-o, --out <path>', 'Output repaired file path')
116
114
  .action(async (file, opts) => {
117
- printBanner();
118
- await debugCommand(file, opts);
119
- });
115
+ printBanner()
116
+ await debugCommand(file, opts)
117
+ })
120
118
 
121
119
  // ─── Global error handling ──────────────────────────────────────────────────
122
- program.exitOverride();
120
+ program.exitOverride()
123
121
 
124
- try {
125
- await program.parseAsync(process.argv);
126
- } catch (err) {
127
- if (err.code === 'commander.helpDisplayed' || err.code === 'commander.version') {
128
- process.exit(0);
122
+ async function main() {
123
+ try {
124
+ await program.parseAsync(process.argv)
125
+ } catch (err) {
126
+ if (err.code === 'commander.helpDisplayed' || err.code === 'commander.version') {
127
+ process.exit(0)
128
+ }
129
+ console.error(chalk.red(`\n✗ Error: ${err.message}\n`))
130
+ process.exit(1)
129
131
  }
130
- console.error(chalk.red(`\n✗ Error: ${err.message}\n`));
131
- process.exit(1);
132
132
  }
133
+
134
+ main()