commit-report-tool/.claude/skills/screenshot-capture/scripts/capture.js
2026-04-03 19:31:32 +09:00

120 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Screenshot Capture Script
*
* HTMLファイルをPNG画像に変換します。
* - Retina対応 (2x)
* - コンテンツサイズに自動フィット(余白なし)
* - GitHub Actions対応Headless
*
* Usage: node capture.js <input.html> <output.png>
*/
const { chromium } = require('playwright');
const path = require('path');
// 設定
const CONFIG = {
scale: parseInt(process.env.SCREENSHOT_SCALE || '2', 10),
width: parseInt(process.env.SCREENSHOT_WIDTH || '450', 10),
wait: parseInt(process.env.SCREENSHOT_WAIT || '500', 10),
};
async function capture(inputPath, outputPath) {
// 入力パスをfile:// URLに変換
const fileUrl = inputPath.startsWith('file://')
? inputPath
: `file://${path.resolve(inputPath)}`;
console.log(`Capturing: ${inputPath}`);
console.log(`Output: ${outputPath}`);
console.log(`Scale: ${CONFIG.scale}x, Width: ${CONFIG.width}px`);
const browser = await chromium.launch({
headless: true,
});
try {
// 高解像度コンテキストを作成
const context = await browser.newContext({
deviceScaleFactor: CONFIG.scale,
viewport: { width: CONFIG.width, height: 800 }, // 初期高さ(後で調整)
});
const page = await context.newPage();
await page.goto(fileUrl, { waitUntil: 'networkidle' });
await page.waitForTimeout(CONFIG.wait);
// コンテンツの実際の高さを取得
const contentHeight = await page.evaluate(() => {
// body直下の最初のdivを探す通常はメインコンテナ
const container = document.body.firstElementChild;
if (container) {
const rect = container.getBoundingClientRect();
// パディングを考慮
const style = window.getComputedStyle(document.body);
const paddingTop = parseFloat(style.paddingTop) || 0;
const paddingBottom = parseFloat(style.paddingBottom) || 0;
return Math.ceil(rect.height + paddingTop + paddingBottom);
}
// フォールバック: body全体の高さ
return document.body.scrollHeight;
});
console.log(`Content height: ${contentHeight}px`);
// ビューポートをコンテンツサイズに合わせる
await page.setViewportSize({
width: CONFIG.width,
height: contentHeight
});
await page.waitForTimeout(100); // レイアウト安定化
// スクリーンショット撮影fullPageではなくビューポートのみ
await page.screenshot({
path: outputPath,
type: 'png',
// fullPage: false がデフォルト
});
console.log(`Done! Saved to ${outputPath}`);
await context.close();
} finally {
await browser.close();
}
}
// メイン処理
async function main() {
const args = process.argv.slice(2);
if (args.length < 2) {
console.error('Usage: node capture.js <input.html> <output.png>');
console.error('');
console.error('Environment variables:');
console.error(' SCREENSHOT_SCALE - Device pixel ratio (default: 2)');
console.error(' SCREENSHOT_WIDTH - Viewport width (default: 450)');
console.error(' SCREENSHOT_WAIT - Wait time in ms (default: 500)');
process.exit(1);
}
const [inputPath, outputPath] = args;
try {
await capture(inputPath, outputPath);
} catch (error) {
console.error('Error:', error.message);
if (error.message.includes('Executable doesn\'t exist')) {
console.error('');
console.error('Chromium is not installed. Run:');
console.error(' npx playwright install chromium');
}
process.exit(1);
}
}
main();