/** * SAM_ERP Storyboard HTML to PPTX Converter (Hybrid Approach) * * - Simple slides: Extracted as editable elements using html2pptx.js * - Complex slides (tables, etc.): Captured as high-resolution images */ const PptxGenJS = require('pptxgenjs'); const html2pptx = require('./html2pptx.js'); const { chromium } = require('playwright'); const path = require('path'); const fs = require('fs'); async function convert() { console.log('SAM_ERP Storyboard HTML to PPTX Conversion (Hybrid)'); console.log('====================================================\n'); // Create new presentation const pres = new PptxGenJS(); // Set presentation properties (720pt x 405pt = 10" x 5.625") pres.defineLayout({ name: 'CUSTOM', width: 10, height: 5.625 }); pres.layout = 'CUSTOM'; pres.title = 'SAM_ERP Storyboard'; pres.author = 'CODE-BRIDGE X'; pres.subject = 'SAM ERP System Storyboard'; // Get all HTML slide files const slidesDir = path.join(__dirname, 'slides'); const imagesDir = path.join(__dirname, 'slide-images'); if (!fs.existsSync(imagesDir)) { fs.mkdirSync(imagesDir, { recursive: true }); } const slideFiles = fs.readdirSync(slidesDir) .filter(f => f.endsWith('.html')) .sort(); console.log(`Found ${slideFiles.length} slides to convert:\n`); // Launch browser for fallback screenshots const browser = await chromium.launch(); const context = await browser.newContext({ viewport: { width: 960, height: 540 } }); const page = await context.newPage(); let editableCount = 0; let imageCount = 0; // Convert each slide for (let i = 0; i < slideFiles.length; i++) { const slideFile = slideFiles[i]; const slidePath = path.join(slidesDir, slideFile); const imagePath = path.join(imagesDir, `slide-${String(i + 1).padStart(2, '0')}.png`); console.log(` [${i + 1}/${slideFiles.length}] ${slideFile}`); try { // Try editable conversion first await html2pptx(slidePath, pres); console.log(` ✓ Editable (elements extracted)`); editableCount++; } catch (err) { // Fallback to image capture console.log(` → Falling back to image capture...`); try { await page.goto(`file:///${slidePath.replace(/\\/g, '/')}`); await page.waitForLoadState('networkidle'); await page.screenshot({ path: imagePath, fullPage: false, clip: { x: 0, y: 0, width: 960, height: 540 } }); const slide = pres.addSlide(); slide.addImage({ path: imagePath, x: 0, y: 0, w: 10, h: 5.625 }); console.log(` ✓ Image (screenshot captured)`); imageCount++; } catch (imgErr) { console.error(` ✗ Failed: ${imgErr.message}`); } } } await browser.close(); // Save to pptx folder const outputDir = path.join(__dirname, 'pptx'); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } const outputPath = path.join(outputDir, 'SAM_ERP_Storyboard_Hybrid.pptx'); console.log('\nSaving presentation...'); await pres.writeFile({ fileName: outputPath }); console.log(`\n✓ Successfully created: ${outputPath}`); console.log(` Total slides: ${slideFiles.length}`); console.log(` Editable slides: ${editableCount}`); console.log(` Image slides: ${imageCount}`); } convert().catch(err => { console.error('Conversion failed:', err); process.exit(1); });