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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-pptx-templater",
3
- "version": "1.0.2",
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
6
  "type": "commonjs",
@@ -2,11 +2,11 @@
2
2
  * @fileoverview `build` CLI command — builds a PPTX from a template + JSON data.
3
3
  */
4
4
 
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');
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.
@@ -16,66 +16,65 @@ const { PPTXTemplater } = require('../../index.js');
16
16
  * @param {Object} opts - CLI options.
17
17
  */
18
18
  async function buildCommand(templatePath, outputPath, opts) {
19
- const spinner = ora(`Loading template: ${templatePath}`).start();
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
  }
80
79
 
81
- module.exports = { buildCommand };
80
+ module.exports = { buildCommand }
@@ -1,47 +1,47 @@
1
1
  /**
2
2
  * @fileoverview `debug` CLI command — diagnoses and repairs corrupted PPTX files.
3
3
  */
4
- const chalk = require('chalk');
5
- const ora = require('ora');
6
- const { resolve } = require('path');
7
- const { PPTXTemplater } = require('../../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
9
  async function debugCommand(filePath, opts) {
10
- const spinner = ora(`Loading PPTX for debug: ${filePath}`).start();
10
+ const spinner = ora(`Loading PPTX for debug: ${filePath}`).start()
11
11
 
12
12
  try {
13
- const ppt = await PPTXTemplater.load(resolve(filePath));
14
- spinner.succeed('Loaded successfully');
13
+ const ppt = await PPTXTemplater.load(resolve(filePath))
14
+ spinner.succeed('Loaded successfully')
15
15
 
16
- const result = ppt.validate();
16
+ const result = ppt.validate()
17
17
 
18
- console.log(chalk.bold.cyan('\n═══ Debug Report ═══\n'));
19
- console.log(chalk.bold('Validation:'));
18
+ console.log(chalk.bold.cyan('\n═══ Debug Report ═══\n'))
19
+ console.log(chalk.bold('Validation:'))
20
20
 
21
21
  if (result.valid) {
22
- console.log(chalk.green(' ✓ Structure is valid'));
22
+ console.log(chalk.green(' ✓ Structure is valid'))
23
23
  } else {
24
- console.log(chalk.red(` ✗ ${result.errors.length} error(s) found`));
25
- 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}`)))
26
26
  }
27
27
 
28
28
  if (result.warnings.length > 0) {
29
- console.log(chalk.yellow(`\n ${result.warnings.length} warning(s):`));
30
- 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}`)))
31
31
  }
32
32
 
33
33
  if (opts.fix && 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}`));
34
+ spinner.start('Attempting repairs...')
35
+ await ppt.saveToFile(resolve(opts.out))
36
+ spinner.succeed(chalk.green(`✓ Repaired PPTX saved to: ${opts.out}`))
37
37
  }
38
38
 
39
- console.log('');
39
+ console.log('')
40
40
  } catch (err) {
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);
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)
44
44
  }
45
45
  }
46
46
 
47
- module.exports = { debugCommand };
47
+ module.exports = { debugCommand }
@@ -1,44 +1,44 @@
1
1
  /**
2
2
  * @fileoverview `extract` CLI command — extracts XML parts from a PPTX.
3
3
  */
4
- const chalk = require('chalk');
5
- const { resolve } = require('path');
6
- const { writeFileSync } = require('fs');
7
- const { PPTXTemplater } = require('../../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
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 = require('jszip');
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
43
 
44
- module.exports = { extractCommand };
44
+ module.exports = { extractCommand }
@@ -1,41 +1,41 @@
1
1
  /**
2
2
  * @fileoverview `inspect` CLI command — detailed PPTX structure inspection.
3
3
  */
4
- const chalk = require('chalk');
5
- const ora = require('ora');
6
- const { resolve } = require('path');
7
- const { PPTXTemplater } = require('../../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
9
  async function inspectCommand(filePath, opts) {
10
- const showAll = opts.all;
11
- const spinner = ora(`Inspecting: ${filePath}`).start();
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
40
 
41
- module.exports = { inspectCommand };
41
+ module.exports = { inspectCommand }
@@ -1,38 +1,38 @@
1
1
  /**
2
2
  * @fileoverview `validate` CLI command.
3
3
  */
4
- const chalk = require('chalk');
5
- const ora = require('ora');
6
- const { resolve } = require('path');
7
- const { PPTXTemplater } = require('../../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
9
  async function validateCommand(filePath, opts) {
10
- const spinner = ora(`Validating: ${filePath}`).start();
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
37
 
38
- module.exports = { validateCommand };
38
+ module.exports = { validateCommand }
package/src/cli/index.js CHANGED
@@ -18,40 +18,43 @@
18
18
  * node-pptx-templater --help
19
19
  */
20
20
 
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');
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')
30
30
 
31
31
  // Read version from package.json
32
- const pkg = JSON.parse(
33
- readFileSync(resolve(__dirname, '../../package.json'), 'utf-8')
34
- );
32
+ const pkg = JSON.parse(readFileSync(resolve(__dirname, '../../package.json'), 'utf-8'))
35
33
 
36
34
  /**
37
35
  * CLI banner displayed on startup.
38
36
  */
39
37
  function printBanner() {
40
- console.log(chalk.bold.cyan(`
38
+ console.log(
39
+ chalk.bold.cyan(`
41
40
  ╔═══════════════════════════════════════════════╗
42
41
  ║ node-pptx-templater v${pkg.version.padEnd(17)}║
43
42
  ║ Low-level OpenXML PowerPoint template engine ║
44
43
  ╚═══════════════════════════════════════════════╝
45
- `));
44
+ `)
45
+ )
46
46
  }
47
47
 
48
- const program = new Command();
48
+ const program = new Command()
49
49
 
50
50
  program
51
51
  .name('node-pptx-templater')
52
52
  .description('Low-level PowerPoint OpenXML template engine for Node.js')
53
53
  .version(pkg.version, '-v, --version', 'Display version number')
54
- .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
+ )
55
58
 
56
59
  // ─── build command ─────────────────────────────────────────────────────────
57
60
  program
@@ -61,9 +64,9 @@ program
61
64
  .option('-s, --slide <numbers>', 'Comma-separated slide numbers to include (e.g., 1,3,5)')
62
65
  .option('--no-banner', 'Suppress the banner')
63
66
  .action(async (template, output, opts) => {
64
- if (!opts.noBanner) printBanner();
65
- await buildCommand(template, output, opts);
66
- });
67
+ if (!opts.noBanner) printBanner()
68
+ await buildCommand(template, output, opts)
69
+ })
67
70
 
68
71
  // ─── validate command ───────────────────────────────────────────────────────
69
72
  program
@@ -71,9 +74,9 @@ program
71
74
  .description('Validate the structure of a PPTX file')
72
75
  .option('--strict', 'Exit with error code on warnings too')
73
76
  .action(async (file, opts) => {
74
- printBanner();
75
- await validateCommand(file, opts);
76
- });
77
+ printBanner()
78
+ await validateCommand(file, opts)
79
+ })
77
80
 
78
81
  // ─── inspect command ────────────────────────────────────────────────────────
79
82
  program
@@ -86,9 +89,9 @@ program
86
89
  .option('--rels', 'Show relationship tree')
87
90
  .option('--all', 'Show everything')
88
91
  .action(async (file, opts) => {
89
- printBanner();
90
- await inspectCommand(file, opts);
91
- });
92
+ printBanner()
93
+ await inspectCommand(file, opts)
94
+ })
92
95
 
93
96
  // ─── extract command ────────────────────────────────────────────────────────
94
97
  program
@@ -99,8 +102,8 @@ program
99
102
  .option('--chart <name>', 'Extract chart XML by name')
100
103
  .option('--rels', 'Extract relationship files')
101
104
  .action(async (file, opts) => {
102
- await extractCommand(file, opts);
103
- });
105
+ await extractCommand(file, opts)
106
+ })
104
107
 
105
108
  // ─── debug command ──────────────────────────────────────────────────────────
106
109
  program
@@ -109,23 +112,23 @@ program
109
112
  .option('--fix', 'Attempt automatic repairs')
110
113
  .option('-o, --out <path>', 'Output repaired file path')
111
114
  .action(async (file, opts) => {
112
- printBanner();
113
- await debugCommand(file, opts);
114
- });
115
+ printBanner()
116
+ await debugCommand(file, opts)
117
+ })
115
118
 
116
119
  // ─── Global error handling ──────────────────────────────────────────────────
117
- program.exitOverride();
120
+ program.exitOverride()
118
121
 
119
122
  async function main() {
120
123
  try {
121
- await program.parseAsync(process.argv);
124
+ await program.parseAsync(process.argv)
122
125
  } catch (err) {
123
126
  if (err.code === 'commander.helpDisplayed' || err.code === 'commander.version') {
124
- process.exit(0);
127
+ process.exit(0)
125
128
  }
126
- console.error(chalk.red(`\n✗ Error: ${err.message}\n`));
127
- process.exit(1);
129
+ console.error(chalk.red(`\n✗ Error: ${err.message}\n`))
130
+ process.exit(1)
128
131
  }
129
132
  }
130
133
 
131
- main();
134
+ main()