215 lines
6.2 KiB
JavaScript
Executable File
215 lines
6.2 KiB
JavaScript
Executable File
#!/usr/bin/env node
|
|
|
|
/**
|
|
* Screenshot Generator for Infinite Agents Dashboard
|
|
*
|
|
* Automatically captures screenshots of all demos for preview thumbnails.
|
|
* Uses Playwright to render each demo and save a screenshot.
|
|
*
|
|
* Installation:
|
|
* npm install -D playwright
|
|
* npx playwright install chromium
|
|
*
|
|
* Usage:
|
|
* node generate_screenshots.js
|
|
* node generate_screenshots.js --category threejs
|
|
* node generate_screenshots.js --single threejs_viz/threejs_viz_1.html
|
|
*/
|
|
|
|
const { chromium } = require('playwright');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
// Demo categories and their file patterns
|
|
const DEMO_CATEGORIES = {
|
|
threejs: {
|
|
pattern: 'threejs_viz/threejs_viz_*.html',
|
|
delay: 3000, // Extra time for WebGL to render
|
|
},
|
|
sdg: {
|
|
pattern: 'sdg_viz/sdg_viz_*.html',
|
|
delay: 2000,
|
|
},
|
|
d3: {
|
|
pattern: 'd3_test/d3_viz_*.html',
|
|
delay: 1500,
|
|
},
|
|
mapbox: {
|
|
pattern: 'mapbox_test/mapbox_globe_*/index.html',
|
|
delay: 3000, // Mapbox needs time to load tiles
|
|
},
|
|
claudeDevTools: {
|
|
pattern: 'claude_code_devtools/claude_devtool_*.html',
|
|
delay: 1000,
|
|
},
|
|
uiSingle: {
|
|
pattern: 'src/ui_hybrid_*.html',
|
|
delay: 800,
|
|
},
|
|
uiInfinite: {
|
|
pattern: 'src_infinite/ui_hybrid_*.html',
|
|
delay: 800,
|
|
},
|
|
uiModular: {
|
|
pattern: 'src_group/ui_hybrid_*/index.html',
|
|
delay: 800,
|
|
},
|
|
infiniteVariants: {
|
|
pattern: 'infinite_variants/infinite_variant_*/test_output/*.html',
|
|
delay: 1500, // Mixed content, some may have animations
|
|
},
|
|
};
|
|
|
|
// Parse command line arguments
|
|
const args = process.argv.slice(2);
|
|
const categoryFilter = args.find(arg => arg.startsWith('--category='))?.split('=')[1];
|
|
const singleFile = args.find(arg => arg.startsWith('--single='))?.split('=')[1];
|
|
const PORT = args.find(arg => arg.startsWith('--port='))?.split('=')[1] || 8889;
|
|
|
|
// Create screenshots directory
|
|
const SCREENSHOTS_DIR = path.join(__dirname, 'screenshots');
|
|
if (!fs.existsSync(SCREENSHOTS_DIR)) {
|
|
fs.mkdirSync(SCREENSHOTS_DIR, { recursive: true });
|
|
console.log(`✅ Created screenshots directory: ${SCREENSHOTS_DIR}`);
|
|
}
|
|
|
|
// Scan directory for demo files
|
|
function scanDirectory(pattern) {
|
|
const glob = require('glob');
|
|
return glob.sync(pattern);
|
|
}
|
|
|
|
// Get all demo files
|
|
function getAllDemos() {
|
|
const demos = [];
|
|
|
|
for (const [category, config] of Object.entries(DEMO_CATEGORIES)) {
|
|
if (categoryFilter && category !== categoryFilter) continue;
|
|
|
|
const files = scanDirectory(config.pattern);
|
|
files.forEach(file => {
|
|
demos.push({
|
|
path: file,
|
|
category,
|
|
delay: config.delay,
|
|
});
|
|
});
|
|
}
|
|
|
|
return demos;
|
|
}
|
|
|
|
// Capture screenshot for a single demo
|
|
async function captureScreenshot(browser, demo, index, total) {
|
|
const page = await browser.newPage();
|
|
|
|
try {
|
|
// Set viewport size (desktop resolution)
|
|
await page.setViewportSize({ width: 1920, height: 1080 });
|
|
|
|
const url = `http://localhost:${PORT}/${demo.path}`;
|
|
console.log(`\n📸 [${index + 1}/${total}] ${demo.path}`);
|
|
|
|
// Navigate to demo
|
|
await page.goto(url, {
|
|
waitUntil: 'networkidle',
|
|
timeout: 30000,
|
|
});
|
|
|
|
// Wait for demo to render
|
|
await page.waitForTimeout(demo.delay);
|
|
|
|
// Generate screenshot filename
|
|
const screenshotFilename = demo.path.replace(/\//g, '_').replace('.html', '.png');
|
|
const screenshotPath = path.join(SCREENSHOTS_DIR, screenshotFilename);
|
|
|
|
// Capture screenshot
|
|
await page.screenshot({
|
|
path: screenshotPath,
|
|
fullPage: false, // Just viewport, not entire scrollable page
|
|
});
|
|
|
|
console.log(` ✅ Saved: ${screenshotFilename}`);
|
|
|
|
} catch (error) {
|
|
console.error(` ❌ Failed: ${error.message}`);
|
|
} finally {
|
|
await page.close();
|
|
}
|
|
}
|
|
|
|
// Main execution
|
|
async function main() {
|
|
console.log('🚀 Infinite Agents Screenshot Generator\n');
|
|
|
|
// Get demo files
|
|
let demos;
|
|
if (singleFile) {
|
|
demos = [{
|
|
path: singleFile,
|
|
category: 'custom',
|
|
delay: 2000,
|
|
}];
|
|
} else {
|
|
demos = getAllDemos();
|
|
}
|
|
|
|
if (demos.length === 0) {
|
|
console.error('❌ No demo files found!');
|
|
console.log('\nMake sure:');
|
|
console.log(' 1. You are in the project root directory');
|
|
console.log(' 2. Demo files exist in their respective directories');
|
|
console.log(' 3. Category filter is correct (if using --category)');
|
|
process.exit(1);
|
|
}
|
|
|
|
console.log(`📊 Found ${demos.length} demos to screenshot\n`);
|
|
|
|
// Check if server is running
|
|
console.log(`🔍 Checking if server is running on http://localhost:${PORT}...`);
|
|
try {
|
|
const http = require('http');
|
|
await new Promise((resolve, reject) => {
|
|
const req = http.get(`http://localhost:${PORT}`, (res) => {
|
|
resolve();
|
|
});
|
|
req.on('error', reject);
|
|
req.setTimeout(3000, () => reject(new Error('Timeout')));
|
|
});
|
|
console.log(' ✅ Server is running\n');
|
|
} catch (error) {
|
|
console.error(' ❌ Server is not running!');
|
|
console.log(`\n🔧 Start the server first:`);
|
|
console.log(` python3 -m http.server ${PORT}\n`);
|
|
process.exit(1);
|
|
}
|
|
|
|
// Launch browser
|
|
console.log('🌐 Launching browser...');
|
|
const browser = await chromium.launch({
|
|
headless: true,
|
|
});
|
|
console.log(' ✅ Browser ready\n');
|
|
|
|
// Capture screenshots
|
|
console.log('📸 Capturing screenshots...');
|
|
console.log('━'.repeat(50));
|
|
|
|
for (let i = 0; i < demos.length; i++) {
|
|
await captureScreenshot(browser, demos[i], i, demos.length);
|
|
}
|
|
|
|
// Cleanup
|
|
await browser.close();
|
|
|
|
console.log('\n' + '━'.repeat(50));
|
|
console.log(`\n✨ Done! Captured ${demos.length} screenshots`);
|
|
console.log(`📁 Screenshots saved to: ${SCREENSHOTS_DIR}\n`);
|
|
}
|
|
|
|
// Run
|
|
main().catch(error => {
|
|
console.error('\n❌ Fatal error:', error);
|
|
process.exit(1);
|
|
});
|