UNPKG

figma-restoration-tools

Version:

Professional Figma Component Restoration Kit - MCP tools with snapDOM-powered high-quality screenshots, intelligent shadow detection, and smart debugging for Vue component restoration. Includes figma_compare and snapdom_screenshot tools.

144 lines (121 loc) 5.34 kB
import fs from 'fs'; import path from 'path'; import { PNG } from 'pngjs'; import pixelmatch from 'pixelmatch'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); async function generateDiffImage(expectedPath, actualPath, outputPath) { try { console.log('Loading images...'); // 读取图片文件 const expectedBuffer = fs.readFileSync(expectedPath); const actualBuffer = fs.readFileSync(actualPath); // 解析PNG const expectedPng = PNG.sync.read(expectedBuffer); const actualPng = PNG.sync.read(actualBuffer); // 使用较小的尺寸进行比较 const width = Math.min(expectedPng.width, actualPng.width); const height = Math.min(expectedPng.height, actualPng.height); console.log(`Expected: ${expectedPng.width}x${expectedPng.height}`); console.log(`Actual: ${actualPng.width}x${actualPng.height}`); console.log(`Comparing: ${width}x${height}`); // 创建输出图像 const diffPng = new PNG({ width, height }); // 生成差异图像 const numDiffPixels = pixelmatch(expectedPng.data, actualPng.data, diffPng.data, width, height, { threshold: 0.1, includeAA: false }); // 保存差异图像 const buffer = PNG.sync.write(diffPng); fs.writeFileSync(outputPath, buffer); const matchPercentage = ((width * height - numDiffPixels) / (width * height) * 100).toFixed(2); console.log(`Diff image saved to: ${outputPath}`); console.log(`Match percentage: ${matchPercentage}%`); console.log(`Different pixels: ${numDiffPixels}`); return { success: true, matchPercentage: parseFloat(matchPercentage), diffPixels: numDiffPixels, dimensions: { width, height } }; } catch (error) { console.error('Error generating diff image:', error); return { success: false, error: error.message }; } } // 处理所有组件 async function processAllComponents() { const resultsDir = path.join(__dirname, '../results'); const publicResultsDir = path.join(__dirname, '../public/results'); const components = ['ModalRemoveMember', 'ExchangeSuccess', 'AssignmentComplete', 'ScanComplete']; const results = {}; for (const component of components) { const expectedPath = path.join(resultsDir, component, `${component}_expected.png`); const actualPath = path.join(resultsDir, component, 'actual.png'); const diffPath = path.join(resultsDir, component, 'diff.png'); const publicDiffPath = path.join(publicResultsDir, component, 'diff.png'); if (fs.existsSync(expectedPath) && fs.existsSync(actualPath)) { console.log(`Processing ${component}...`); const result = await generateDiffImage(expectedPath, actualPath, diffPath); if (result.success) { // 复制到public目录 fs.copyFileSync(diffPath, publicDiffPath); console.log(`✅ ${component} diff image generated`); // 生成报告JSON const reportData = { componentName: component, timestamp: new Date().toISOString(), summary: { matchPercentage: result.matchPercentage, pixelMatch: result.diffPixels, componentCreated: true, componentRendered: true, screenshotTaken: true, comparisonAvailable: true, files: { component: `/mcp-vue-tools/src/components/${component}/index.vue`, screenshot: `/results/${component}/actual.png`, expected: `/results/${component}/expected.png`, diff: `/results/${component}/diff.png` }, urls: { test: `http://localhost:83/component/${component}`, figma: "https://www.figma.com/design/" } }, comparison: { expectedDimensions: result.dimensions, actualDimensions: result.dimensions, diffDimensions: result.dimensions, dimensionMismatch: false }, steps: { create: { success: true, message: "Component created successfully" }, render: { success: true, message: "Component rendered successfully" }, screenshot: { success: true, message: "Screenshot captured successfully" }, comparison: { success: true, message: `Image comparison completed with ${result.matchPercentage}% match` } } }; // 保存报告 const reportPath = path.join(publicResultsDir, component, 'report.json'); fs.writeFileSync(reportPath, JSON.stringify(reportData, null, 2)); results[component] = result; } else { console.log(`❌ ${component} diff image failed: ${result.error}`); results[component] = result; } } else { console.log(`⚠️ ${component} missing images`); console.log(`Expected: ${fs.existsSync(expectedPath) ? '✓' : '✗'} ${expectedPath}`); console.log(`Actual: ${fs.existsSync(actualPath) ? '✓' : '✗'} ${actualPath}`); results[component] = { success: false, error: 'Missing images' }; } } return results; } if (import.meta.url === `file://${process.argv[1]}`) { processAllComponents().catch(console.error); } export { generateDiffImage, processAllComponents };