spa/.claude/skills/drawnote/scripts/capture.js

202 lines
6.0 KiB
JavaScript
Raw Permalink 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
/**
* 使用 Playwright 截取 HTML 文件的截图
*
* 使用方法:
* node capture.js <html-file-path> <output-image-path> [options]
*
* 参数:
* html-file-path: 输入的 HTML 文件路径
* output-image-path: 输出的 PNG 图片路径
*
* 选项:
* --width: 视口宽度 (默认: 1920)
* --height: 视口高度 (默认: auto自动适应内容高度)
* --full-page: 截取整个页面 (默认: true)
* --wait: 等待时间(毫秒),确保页面完全渲染 (默认: 1000)
*
* 示例:
* node capture.js input.html output.png
* node capture.js input.html output.png --width 1920 --height 1080 --full-page
* node capture.js input.html output.png --wait 2000
*/
const { chromium } = require('playwright');
const fs = require('fs');
const path = require('path');
// 解析命令行参数
function parseArgs() {
const args = process.argv.slice(2);
if (args.length < 2) {
console.error('错误: 需要提供 HTML 文件路径和输出图片路径');
console.error('使用方法: node capture.js <html-file-path> <output-image-path> [options]');
process.exit(1);
}
const config = {
htmlPath: args[0],
outputPath: args[1],
width: 1920,
height: 1080,
fullPage: true,
wait: 1000
};
// 解析选项
for (let i = 2; i < args.length; i++) {
if (args[i] === '--width' && i + 1 < args.length) {
config.width = parseInt(args[i + 1]);
i++;
} else if (args[i] === '--height' && i + 1 < args.length) {
config.height = parseInt(args[i + 1]);
i++;
} else if (args[i] === '--full-page') {
config.fullPage = true;
} else if (args[i] === '--wait' && i + 1 < args.length) {
config.wait = parseInt(args[i + 1]);
i++;
}
}
return config;
}
// 验证文件
function validateFiles(config) {
// 检查输入文件是否存在
if (!fs.existsSync(config.htmlPath)) {
console.error(`错误: HTML 文件不存在: ${config.htmlPath}`);
process.exit(1);
}
// 确保输出目录存在
const outputDir = path.dirname(config.outputPath);
if (!fs.existsSync(outputDir)) {
fs.mkdirSync(outputDir, { recursive: true });
}
}
// 主函数
async function captureScreenshot() {
const config = parseArgs();
validateFiles(config);
console.log('截图配置:');
console.log(` HTML 文件: ${config.htmlPath}`);
console.log(` 输出路径: ${config.outputPath}`);
console.log(` 视口大小: ${config.width}x${config.height}`);
console.log(` 整页截图: ${config.fullPage ? '是' : '否'}`);
console.log(` 等待时间: ${config.wait}ms`);
console.log('');
let browser;
try {
// 启动浏览器
console.log('启动浏览器...');
browser = await chromium.launch({
headless: true,
args: [
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-dev-shm-usage',
'--disable-accelerated-2d-canvas',
'--no-first-run',
'--no-zygote',
'--disable-gpu'
]
});
// 创建页面
const context = await browser.newContext({
viewport: {
width: config.width,
height: config.height
},
acceptDownloads: true,
ignoreHTTPSErrors: true
});
const page = await context.newPage();
// 设置页面默认行为,避免弹窗
page.on('dialog', async dialog => {
await dialog.accept();
});
// 转换为绝对路径
const absoluteHtmlPath = path.resolve(config.htmlPath);
const fileUrl = `file://${absoluteHtmlPath}`;
console.log(`加载页面: ${fileUrl}`);
await page.goto(fileUrl, {
waitUntil: 'networkidle',
timeout: 30000
});
// 等待页面完全渲染
console.log(`等待 ${config.wait}ms 确保页面完全渲染...`);
await page.waitForTimeout(config.wait);
// 等待所有图片加载完成
await page.evaluate(() => {
return Promise.all(
Array.from(document.images)
.filter(img => !img.complete)
.map(img => new Promise(resolve => {
img.onload = img.onerror = resolve;
}))
);
});
// 如果启用了 fullPage获取实际内容高度
if (config.fullPage) {
const contentHeight = await page.evaluate(() => {
return Math.max(
document.documentElement.scrollHeight,
document.documentElement.offsetHeight,
document.body.scrollHeight,
document.body.offsetHeight
);
});
console.log(`检测到内容高度: ${contentHeight}px`);
// 设置足够的视口高度来容纳完整内容
await page.setViewportSize({
width: config.width,
height: Math.max(contentHeight + 100, config.height)
});
}
// 截图
console.log('正在截图...');
await page.screenshot({
path: config.outputPath,
fullPage: config.fullPage,
type: 'png'
});
console.log(`✓ 截图成功保存至: ${config.outputPath}`);
// 获取文件大小
const stats = fs.statSync(config.outputPath);
const fileSizeMB = (stats.size / (1024 * 1024)).toFixed(2);
console.log(` 文件大小: ${fileSizeMB} MB`);
await browser.close();
process.exit(0);
} catch (error) {
console.error('错误:', error.message);
if (browser) {
await browser.close();
}
process.exit(1);
}
}
// 运行
captureScreenshot();