@calibrate-ds/core 0.1.39 → 0.1.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -2,13 +2,16 @@ import type { PixelMatchResult } from "./types.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Compares two PNG files pixel-by-pixel using pixelmatch.
|
|
4
4
|
* Saves an annotated diff image to diffOutputPath.
|
|
5
|
-
* Returns the match
|
|
5
|
+
* Returns the match scores (0–1, 1 = identical), or null if comparison fails.
|
|
6
6
|
*
|
|
7
|
-
* Dimension mismatch
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
7
|
+
* Dimension mismatch: always scale impl to Figma reference dimensions (never pad
|
|
8
|
+
* with white, which inflates scores on mostly-white components).
|
|
9
|
+
*
|
|
10
|
+
* Content score: if high-variance (photographic/raster) regions are detected in
|
|
11
|
+
* the Figma reference, a second masked comparison excludes those patches and
|
|
12
|
+
* reports contentScore — the fidelity of the non-image UI regions only. This
|
|
13
|
+
* prevents placeholder-image differences from killing the score for otherwise
|
|
14
|
+
* faithful implementations.
|
|
12
15
|
*/
|
|
13
16
|
export declare function runPixelDiff(figmaPath: string, implPath: string, diffOutputPath: string): Promise<PixelMatchResult | null>;
|
|
14
17
|
//# sourceMappingURL=pixel-diff.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixel-diff.d.ts","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"pixel-diff.d.ts","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAgGnD;;;;;;;;;;;;;GAaG;AACH,wBAAsB,YAAY,CAC9B,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,MAAM,GACvB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAoElC"}
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import * as fs from "node:fs/promises";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
+
// Patch size (px) and luminance-variance threshold for raster region detection.
|
|
4
|
+
// Photos/textures → variance >> 600; flat UI (solid fills, gradients) → variance < 300.
|
|
5
|
+
const PATCH_SIZE = 16;
|
|
6
|
+
const RASTER_VARIANCE_THRESHOLD = 600;
|
|
3
7
|
/**
|
|
4
|
-
* Nearest-neighbor
|
|
5
|
-
*
|
|
6
|
-
* shifted" artifact that crop/pad produces on retina captures.
|
|
8
|
+
* Nearest-neighbor scale to target dimensions (handles both up and down).
|
|
9
|
+
* Used to align impl screenshot to Figma reference dimensions before diffing.
|
|
7
10
|
*/
|
|
8
11
|
function scaleDown(src, targetW, targetH, PNG) {
|
|
9
12
|
const out = new PNG({ width: targetW, height: targetH });
|
|
@@ -23,16 +26,69 @@ function scaleDown(src, targetW, targetH, PNG) {
|
|
|
23
26
|
}
|
|
24
27
|
return out;
|
|
25
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Divides the Figma reference into PATCH_SIZE×PATCH_SIZE tiles and marks tiles
|
|
31
|
+
* whose luminance variance exceeds RASTER_VARIANCE_THRESHOLD as "raster" patches.
|
|
32
|
+
* Returns the boolean mask (indexed row-major by patch) plus the patch grid dimensions.
|
|
33
|
+
*/
|
|
34
|
+
function buildRasterMask(data, imgWidth, imgHeight, patchSize, threshold) {
|
|
35
|
+
const patchCols = Math.ceil(imgWidth / patchSize);
|
|
36
|
+
const patchRows = Math.ceil(imgHeight / patchSize);
|
|
37
|
+
const mask = [];
|
|
38
|
+
for (let pr = 0; pr < patchRows; pr++) {
|
|
39
|
+
for (let pc = 0; pc < patchCols; pc++) {
|
|
40
|
+
const lums = [];
|
|
41
|
+
for (let py = pr * patchSize; py < Math.min((pr + 1) * patchSize, imgHeight); py++) {
|
|
42
|
+
for (let px = pc * patchSize; px < Math.min((pc + 1) * patchSize, imgWidth); px++) {
|
|
43
|
+
const i = (py * imgWidth + px) * 4;
|
|
44
|
+
lums.push(0.299 * data[i] + 0.587 * data[i + 1] + 0.114 * data[i + 2]);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
const mean = lums.reduce((a, b) => a + b, 0) / lums.length;
|
|
48
|
+
const variance = lums.reduce((acc, v) => acc + (v - mean) ** 2, 0) / lums.length;
|
|
49
|
+
mask.push(variance > threshold);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return { mask, patchCols, patchRows };
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Fills masked patches in-place with neutral mid-gray (128,128,128,255).
|
|
56
|
+
* When applied to both images before pixelmatch, masked patches contribute
|
|
57
|
+
* 0 diff pixels, so only non-masked (content) pixels affect the score.
|
|
58
|
+
* Returns the number of pixels filled.
|
|
59
|
+
*/
|
|
60
|
+
function applyRasterMask(target, mask, patchSize, patchCols, imgWidth, imgHeight) {
|
|
61
|
+
const patchRows = Math.ceil(imgHeight / patchSize);
|
|
62
|
+
let maskedPixels = 0;
|
|
63
|
+
for (let pr = 0; pr < patchRows; pr++) {
|
|
64
|
+
for (let pc = 0; pc < patchCols; pc++) {
|
|
65
|
+
if (!mask[pr * patchCols + pc])
|
|
66
|
+
continue;
|
|
67
|
+
for (let py = pr * patchSize; py < Math.min((pr + 1) * patchSize, imgHeight); py++) {
|
|
68
|
+
for (let px = pc * patchSize; px < Math.min((pc + 1) * patchSize, imgWidth); px++) {
|
|
69
|
+
const i = (py * imgWidth + px) * 4;
|
|
70
|
+
target[i] = target[i + 1] = target[i + 2] = 128;
|
|
71
|
+
target[i + 3] = 255;
|
|
72
|
+
maskedPixels++;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
return maskedPixels;
|
|
78
|
+
}
|
|
26
79
|
/**
|
|
27
80
|
* Compares two PNG files pixel-by-pixel using pixelmatch.
|
|
28
81
|
* Saves an annotated diff image to diffOutputPath.
|
|
29
|
-
* Returns the match
|
|
82
|
+
* Returns the match scores (0–1, 1 = identical), or null if comparison fails.
|
|
83
|
+
*
|
|
84
|
+
* Dimension mismatch: always scale impl to Figma reference dimensions (never pad
|
|
85
|
+
* with white, which inflates scores on mostly-white components).
|
|
30
86
|
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
87
|
+
* Content score: if high-variance (photographic/raster) regions are detected in
|
|
88
|
+
* the Figma reference, a second masked comparison excludes those patches and
|
|
89
|
+
* reports contentScore — the fidelity of the non-image UI regions only. This
|
|
90
|
+
* prevents placeholder-image differences from killing the score for otherwise
|
|
91
|
+
* faithful implementations.
|
|
36
92
|
*/
|
|
37
93
|
export async function runPixelDiff(figmaPath, implPath, diffOutputPath) {
|
|
38
94
|
try {
|
|
@@ -41,49 +97,36 @@ export async function runPixelDiff(figmaPath, implPath, diffOutputPath) {
|
|
|
41
97
|
const figmaPng = PNG.sync.read(await fs.readFile(figmaPath));
|
|
42
98
|
let implPng = PNG.sync.read(await fs.readFile(implPath));
|
|
43
99
|
const { width, height } = figmaPng;
|
|
44
|
-
// Align impl to Figma dimensions
|
|
100
|
+
// Align impl to Figma dimensions — scale always, never pad with white.
|
|
45
101
|
if (implPng.width !== width || implPng.height !== height) {
|
|
46
|
-
|
|
47
|
-
const hRatio = implPng.height / height;
|
|
48
|
-
if (wRatio >= 1.5 && hRatio >= 1.5) {
|
|
49
|
-
// Oversized capture (e.g. 2× DPR retina screenshot) — scale down so
|
|
50
|
-
// every row aligns instead of being cropped at the halfway point.
|
|
51
|
-
implPng = scaleDown(implPng, width, height, PNG);
|
|
52
|
-
}
|
|
53
|
-
else {
|
|
54
|
-
// Small mismatch — crop/pad to reference size
|
|
55
|
-
const aligned = new PNG({ width, height });
|
|
56
|
-
for (let i = 0; i < aligned.data.length; i += 4) {
|
|
57
|
-
aligned.data[i] = 255;
|
|
58
|
-
aligned.data[i + 1] = 255;
|
|
59
|
-
aligned.data[i + 2] = 255;
|
|
60
|
-
aligned.data[i + 3] = 255;
|
|
61
|
-
}
|
|
62
|
-
const copyW = Math.min(width, implPng.width);
|
|
63
|
-
const copyH = Math.min(height, implPng.height);
|
|
64
|
-
for (let y = 0; y < copyH; y++) {
|
|
65
|
-
for (let x = 0; x < copyW; x++) {
|
|
66
|
-
const s = (y * implPng.width + x) * 4;
|
|
67
|
-
const d = (y * width + x) * 4;
|
|
68
|
-
aligned.data[d] = implPng.data[s];
|
|
69
|
-
aligned.data[d + 1] = implPng.data[s + 1];
|
|
70
|
-
aligned.data[d + 2] = implPng.data[s + 2];
|
|
71
|
-
aligned.data[d + 3] = implPng.data[s + 3];
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
implPng = aligned;
|
|
75
|
-
}
|
|
102
|
+
implPng = scaleDown(implPng, width, height, PNG);
|
|
76
103
|
}
|
|
104
|
+
// ── Full-frame diff (primary score + diff image) ─────────────────────
|
|
77
105
|
const diffPng = new PNG({ width, height });
|
|
78
106
|
const totalPixels = width * height;
|
|
79
107
|
const diffPixels = pixelmatch(figmaPng.data, implPng.data, diffPng.data, width, height, { threshold: 0.1, includeAA: false });
|
|
80
108
|
await fs.mkdir(path.dirname(diffOutputPath), { recursive: true });
|
|
81
109
|
await fs.writeFile(diffOutputPath, PNG.sync.write(diffPng));
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
110
|
+
const score = parseFloat((1 - diffPixels / totalPixels).toFixed(4));
|
|
111
|
+
// ── Content-only score (exclude raster image patches) ────────────────
|
|
112
|
+
const { mask, patchCols } = buildRasterMask(figmaPng.data, width, height, PATCH_SIZE, RASTER_VARIANCE_THRESHOLD);
|
|
113
|
+
const rasterPatchCount = mask.filter(Boolean).length;
|
|
114
|
+
if (rasterPatchCount === 0) {
|
|
115
|
+
return { score, diffPixels, totalPixels };
|
|
116
|
+
}
|
|
117
|
+
// At least one raster patch: run a second comparison on masked copies.
|
|
118
|
+
// Both images get the same patches filled with mid-gray → pixelmatch sees
|
|
119
|
+
// 0 diff in those patches → contentDiffPixels counts content regions only.
|
|
120
|
+
const figmaMasked = Buffer.from(figmaPng.data);
|
|
121
|
+
const implMasked = Buffer.from(implPng.data);
|
|
122
|
+
const maskedPixels = applyRasterMask(figmaMasked, mask, PATCH_SIZE, patchCols, width, height);
|
|
123
|
+
applyRasterMask(implMasked, mask, PATCH_SIZE, patchCols, width, height);
|
|
124
|
+
const diffMasked = new PNG({ width, height });
|
|
125
|
+
const contentDiffPixels = pixelmatch(figmaMasked, implMasked, diffMasked.data, width, height, { threshold: 0.1, includeAA: false });
|
|
126
|
+
const contentPixels = totalPixels - maskedPixels;
|
|
127
|
+
const contentScore = parseFloat((contentPixels > 0 ? 1 - contentDiffPixels / contentPixels : 1).toFixed(4));
|
|
128
|
+
const rasterPixelRatio = parseFloat((maskedPixels / totalPixels).toFixed(4));
|
|
129
|
+
return { score, contentScore, rasterPixelRatio, diffPixels, totalPixels };
|
|
87
130
|
}
|
|
88
131
|
catch {
|
|
89
132
|
return null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pixel-diff.js","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAIlC
|
|
1
|
+
{"version":3,"file":"pixel-diff.js","sourceRoot":"","sources":["../../src/verify/pixel-diff.ts"],"names":[],"mappings":"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"}
|
package/dist/verify/types.d.ts
CHANGED
|
@@ -6,7 +6,16 @@ export type VerifyScreenshots = {
|
|
|
6
6
|
diff: string | null;
|
|
7
7
|
};
|
|
8
8
|
export type PixelMatchResult = {
|
|
9
|
+
/** Full-frame raw pixel match score (0–1, 1 = identical). */
|
|
9
10
|
score: number;
|
|
11
|
+
/**
|
|
12
|
+
* Score computed only over non-raster regions — excludes high-variance patches
|
|
13
|
+
* (detected photographic images) that are expected to differ (placeholder vs real asset).
|
|
14
|
+
* Present only when at least one raster patch was detected.
|
|
15
|
+
*/
|
|
16
|
+
contentScore?: number;
|
|
17
|
+
/** Fraction of total pixels identified as raster image regions (0–1). */
|
|
18
|
+
rasterPixelRatio?: number;
|
|
10
19
|
diffPixels: number;
|
|
11
20
|
totalPixels: number;
|
|
12
21
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/verify/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yFAAyF;IACzF,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACzC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,iBAAiB,EAAE,SAAS,GAAG,mBAAmB,GAAG,yBAAyB,CAAC;CAClF,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;IAClB,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/verify/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,iBAAiB,GAAG;IAC5B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,yFAAyF;IACzF,WAAW,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAAC;IACzC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC3B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,YAAY,EAAE,CAAC;IAC5B,iBAAiB,EAAE,SAAS,GAAG,mBAAmB,GAAG,yBAAyB,CAAC;CAClF,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,WAAW,EAAE,iBAAiB,CAAC;IAC/B,UAAU,EAAE,gBAAgB,GAAG,IAAI,CAAC;IACpC,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,qFAAqF;IACrF,QAAQ,EAAE,OAAO,CAAC;IAClB,gGAAgG;IAChG,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gDAAgD;IAChD,KAAK,CAAC,EAAE,MAAM,CAAC;CAClB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@calibrate-ds/core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.41",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -27,8 +27,8 @@
|
|
|
27
27
|
"pixelmatch": "^6.0.0",
|
|
28
28
|
"pngjs": "^7.0.0",
|
|
29
29
|
"zod": "^4.3.6",
|
|
30
|
-
"@calibrate-ds/
|
|
31
|
-
"@calibrate-ds/
|
|
30
|
+
"@calibrate-ds/shared-types": "^0.1.41",
|
|
31
|
+
"@calibrate-ds/figma-client": "^0.1.41"
|
|
32
32
|
},
|
|
33
33
|
"scripts": {
|
|
34
34
|
"build": "tsc -p tsconfig.json",
|