Newer
Older
vmk-ui-kit / scripts / compare-with-figma.js
#!/usr/bin/env node
/**
 * Standalone script to compare a rendered demo screenshot with a Figma PNG.
 *
 * Usage:
 *   node scripts/compare-with-figma.js <screenshot.png> <figma-frame.png> [out-diff.png]
 */

const fs = require("fs");
const path = require("path");
const PNG = require("pngjs").PNG;
const pixelmatch = require("pixelmatch").default || require("pixelmatch");
const sharp = require("sharp");

async function main() {
  const [screenshotPath, framePath, diffPathArg] = process.argv.slice(2);
  if (!screenshotPath || !framePath) {
    console.error("Usage: node scripts/compare-with-figma.js <screenshot.png> <figma-frame.png> [out-diff.png]");
    process.exit(1);
  }

  const diffPath = diffPathArg || path.join(path.dirname(screenshotPath), `diff-${path.basename(screenshotPath)}`);

  const screenshot = await sharp(screenshotPath)
    .ensureAlpha()
    .raw()
    .toBuffer({ resolveWithObject: true });

  const frame = await sharp(framePath)
    .ensureAlpha()
    .resize(screenshot.info.width, screenshot.info.height, { fit: "fill" })
    .raw()
    .toBuffer({ resolveWithObject: true });

  const diff = Buffer.alloc(screenshot.info.width * screenshot.info.height * 4);
  const mismatched = pixelmatch(
    screenshot.data,
    frame.data,
    diff,
    screenshot.info.width,
    screenshot.info.height,
    { threshold: 0.1, includeAA: false }
  );

  await sharp(diff, {
    raw: { width: screenshot.info.width, height: screenshot.info.height, channels: 4 }
  }).png().toFile(diffPath);

  const total = screenshot.info.width * screenshot.info.height;
  console.log(`Pixels: ${total}`);
  console.log(`Mismatched: ${mismatched}`);
  console.log(`Ratio: ${(mismatched / total * 100).toFixed(2)}%`);
  console.log(`Diff saved to: ${diffPath}`);
}

main().catch(err => {
  console.error(err);
  process.exit(1);
});