claude-presentation-master 2.1.2 → 3.6.0

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.
@@ -0,0 +1,91 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <style>
5
+ * { margin: 0; padding: 0; box-sizing: border-box; }
6
+ body {
7
+ font-family: 'IBM Plex Sans', -apple-system, sans-serif;
8
+ background: #ffffff;
9
+ color: #003366;
10
+ height: 100vh;
11
+ padding: 50px 70px;
12
+ }
13
+ h1 {
14
+ font-size: 2rem;
15
+ font-weight: 600;
16
+ margin-bottom: 40px;
17
+ border-bottom: 3px solid #003366;
18
+ padding-bottom: 15px;
19
+ }
20
+ .content {
21
+ display: flex;
22
+ gap: 50px;
23
+ }
24
+ .left {
25
+ flex: 1;
26
+ }
27
+ .right {
28
+ flex: 1;
29
+ }
30
+ h2 {
31
+ font-size: 1.3rem;
32
+ font-weight: 600;
33
+ margin-bottom: 20px;
34
+ color: #003366;
35
+ }
36
+ ul {
37
+ list-style: none;
38
+ }
39
+ li {
40
+ padding: 12px 0;
41
+ border-bottom: 1px solid #e0e0e0;
42
+ font-size: 1.1rem;
43
+ color: #333;
44
+ }
45
+ li:before {
46
+ content: "→";
47
+ color: #0066cc;
48
+ margin-right: 12px;
49
+ }
50
+ .metric-box {
51
+ background: #f5f7fa;
52
+ padding: 25px;
53
+ margin-bottom: 20px;
54
+ border-left: 4px solid #003366;
55
+ }
56
+ .metric-value {
57
+ font-size: 2.5rem;
58
+ font-weight: 700;
59
+ color: #003366;
60
+ }
61
+ .metric-label {
62
+ color: #666;
63
+ margin-top: 5px;
64
+ }
65
+ </style>
66
+ </head>
67
+ <body>
68
+ <h1>Digital transformation will reduce costs 25% and improve NPS by 15 points</h1>
69
+ <div class="content">
70
+ <div class="left">
71
+ <h2>Recommended Actions</h2>
72
+ <ul>
73
+ <li>Migrate to cloud infrastructure (Q1-Q2)</li>
74
+ <li>Implement customer portal redesign</li>
75
+ <li>Automate invoice processing</li>
76
+ <li>Deploy predictive analytics</li>
77
+ </ul>
78
+ </div>
79
+ <div class="right">
80
+ <div class="metric-box">
81
+ <div class="metric-value">$42M</div>
82
+ <div class="metric-label">3-Year NPV</div>
83
+ </div>
84
+ <div class="metric-box">
85
+ <div class="metric-value">35%</div>
86
+ <div class="metric-label">IRR</div>
87
+ </div>
88
+ </div>
89
+ </div>
90
+ </body>
91
+ </html>
@@ -0,0 +1,32 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <style>
5
+ * { margin: 0; padding: 0; box-sizing: border-box; }
6
+ body {
7
+ font-family: 'DM Sans', -apple-system, sans-serif;
8
+ background: #000000;
9
+ color: white;
10
+ height: 100vh;
11
+ display: flex;
12
+ flex-direction: column;
13
+ justify-content: center;
14
+ align-items: center;
15
+ padding: 60px;
16
+ }
17
+ h1 {
18
+ font-size: 5rem;
19
+ font-weight: 700;
20
+ text-align: center;
21
+ line-height: 1.1;
22
+ max-width: 900px;
23
+ }
24
+ .highlight {
25
+ color: #e62b1e;
26
+ }
27
+ </style>
28
+ </head>
29
+ <body>
30
+ <h1>By 2030, <span class="highlight">85%</span> of jobs will be ones that don't exist today.</h1>
31
+ </body>
32
+ </html>
@@ -0,0 +1,64 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <style>
5
+ * { margin: 0; padding: 0; box-sizing: border-box; }
6
+ body {
7
+ font-family: 'Poppins', -apple-system, sans-serif;
8
+ background: linear-gradient(135deg, #1e40af 0%, #3b82f6 100%);
9
+ color: white;
10
+ height: 100vh;
11
+ display: flex;
12
+ flex-direction: column;
13
+ justify-content: center;
14
+ align-items: center;
15
+ padding: 60px;
16
+ }
17
+ h1 {
18
+ font-size: 4rem;
19
+ font-weight: 700;
20
+ margin-bottom: 20px;
21
+ text-align: center;
22
+ }
23
+ .subtitle {
24
+ font-size: 1.8rem;
25
+ opacity: 0.9;
26
+ margin-bottom: 60px;
27
+ }
28
+ .stats {
29
+ display: flex;
30
+ gap: 80px;
31
+ }
32
+ .stat {
33
+ text-align: center;
34
+ }
35
+ .stat-number {
36
+ font-size: 3.5rem;
37
+ font-weight: 700;
38
+ color: #10b981;
39
+ }
40
+ .stat-label {
41
+ font-size: 1.2rem;
42
+ opacity: 0.8;
43
+ }
44
+ </style>
45
+ </head>
46
+ <body>
47
+ <h1>Cut Costs by 40%</h1>
48
+ <p class="subtitle">500+ companies already did</p>
49
+ <div class="stats">
50
+ <div class="stat">
51
+ <div class="stat-number">$2.4M</div>
52
+ <div class="stat-label">Average Savings</div>
53
+ </div>
54
+ <div class="stat">
55
+ <div class="stat-number">92%</div>
56
+ <div class="stat-label">Customer Retention</div>
57
+ </div>
58
+ <div class="stat">
59
+ <div class="stat-number">3 Days</div>
60
+ <div class="stat-label">Implementation</div>
61
+ </div>
62
+ </div>
63
+ </body>
64
+ </html>
package/bin/cli.js CHANGED
@@ -11,8 +11,8 @@
11
11
  * cpm --help
12
12
  */
13
13
 
14
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
15
- import { resolve, dirname, basename, extname } from 'path';
14
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, readdirSync } from 'fs';
15
+ import { resolve, dirname, basename, extname, join } from 'path';
16
16
  import { fileURLToPath } from 'url';
17
17
 
18
18
  // Parse command line arguments
@@ -293,6 +293,48 @@ Usage:
293
293
  }
294
294
  }
295
295
 
296
+ /**
297
+ * Scan directory for image files (jpg, jpeg, png, gif, webp, svg).
298
+ * Returns paths relative to the directory.
299
+ */
300
+ function scanForImages(directory) {
301
+ const imageExtensions = ['.jpg', '.jpeg', '.png', '.gif', '.webp', '.svg'];
302
+ const images = [];
303
+
304
+ // Scan the directory and images subdirectory
305
+ const dirsToScan = [directory];
306
+ const imagesDir = join(directory, 'images');
307
+ if (existsSync(imagesDir)) {
308
+ dirsToScan.push(imagesDir);
309
+ }
310
+ const screenshotsDir = join(directory, 'screenshots');
311
+ if (existsSync(screenshotsDir)) {
312
+ dirsToScan.push(screenshotsDir);
313
+ }
314
+ const assetsDir = join(directory, 'assets');
315
+ if (existsSync(assetsDir)) {
316
+ dirsToScan.push(assetsDir);
317
+ }
318
+
319
+ for (const dir of dirsToScan) {
320
+ try {
321
+ const files = readdirSync(dir);
322
+ for (const file of files) {
323
+ const ext = extname(file).toLowerCase();
324
+ if (imageExtensions.includes(ext)) {
325
+ // Store relative path from input directory
326
+ const relativePath = dir === directory ? file : join(basename(dir), file);
327
+ images.push(relativePath);
328
+ }
329
+ }
330
+ } catch (e) {
331
+ // Directory might not exist or not be readable
332
+ }
333
+ }
334
+
335
+ return images;
336
+ }
337
+
296
338
  // Generate command
297
339
  async function runGenerate(inputPath, options, generate) {
298
340
  console.log(`
@@ -306,6 +348,13 @@ async function runGenerate(inputPath, options, generate) {
306
348
  console.log(`šŸ“„ Reading: ${inputPath}`);
307
349
  const content = readFileSync(inputPath, 'utf-8');
308
350
 
351
+ // Scan for local images in input directory
352
+ const inputDir = dirname(inputPath);
353
+ const localImages = scanForImages(inputDir);
354
+ if (localImages.length > 0) {
355
+ console.log(`šŸ–¼ļø Found ${localImages.length} local images: ${localImages.slice(0, 3).join(', ')}${localImages.length > 3 ? '...' : ''}`);
356
+ }
357
+
309
358
  // Determine title
310
359
  const title = options.title || basename(inputPath, extname(inputPath));
311
360
 
@@ -320,7 +369,9 @@ async function runGenerate(inputPath, options, generate) {
320
369
  title,
321
370
  author: options.author,
322
371
  qaThreshold: options.threshold,
323
- skipQA: options.skipQA
372
+ skipQA: options.skipQA,
373
+ images: localImages, // Local images for backgrounds
374
+ imageBasePath: inputDir // Base path for resolving relative image paths
324
375
  };
325
376
 
326
377
  console.log(`
@@ -360,6 +411,9 @@ async function runGenerate(inputPath, options, generate) {
360
411
  }
361
412
 
362
413
  // Show results
414
+ const avgWords = result.metadata.avgWordsPerSlide?.toFixed(1) ?? 'N/A';
415
+ const estimatedDuration = Math.ceil((result.metadata.totalWords || 0) / 150); // ~150 words per minute
416
+
363
417
  console.log(`
364
418
  ╔════════════════════════════════════════════════════════╗
365
419
  ā•‘ QA RESULTS ā•‘
@@ -369,24 +423,12 @@ async function runGenerate(inputPath, options, generate) {
369
423
 
370
424
  šŸ“ˆ Metadata:
371
425
  Slides: ${result.metadata.slideCount}
372
- Words: ${result.metadata.wordCount}
373
- Avg/Slide: ${result.metadata.avgWordsPerSlide}
374
- Duration: ~${result.metadata.estimatedDuration} minutes
375
-
376
- šŸŽ“ Frameworks Applied:
377
- ${result.metadata.frameworks.map(f => ` • ${f}`).join('\n') || ' (none detected)'}
426
+ Words: ${result.metadata.totalWords || 'N/A'}
427
+ Avg/Slide: ${avgWords}
428
+ Duration: ~${estimatedDuration} minutes
429
+ Type: ${result.metadata.presentationType}
378
430
  `);
379
431
 
380
- // Show issues if any
381
- const errors = result.qaResults.issues.filter(i => i.severity === 'error');
382
- const warnings = result.qaResults.issues.filter(i => i.severity === 'warning');
383
-
384
- if (errors.length > 0 || warnings.length > 0) {
385
- console.log('āš ļø Issues:');
386
- errors.forEach(e => console.log(` āŒ ${e.message}`));
387
- warnings.forEach(w => console.log(` āš ļø ${w.message}`));
388
- }
389
-
390
432
  console.log('\n✨ Generation complete!');
391
433
 
392
434
  } catch (error) {