@blazediff/matcher 1.1.1 → 1.2.0

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.
package/dist/index.d.mts CHANGED
@@ -7,9 +7,9 @@ type ComparisonMethod = "bin" | "core" | "ssim" | "msssim" | "hitchhikers-ssim"
7
7
  */
8
8
  type SnapshotStatus = "added" | "matched" | "updated" | "failed";
9
9
  /**
10
- * Image input - either a file path or a buffer with dimensions
10
+ * Image input - file path, raw PNG buffer, or buffer with dimensions
11
11
  */
12
- type ImageInput = string | {
12
+ type ImageInput = string | Buffer | Uint8Array | {
13
13
  data: Uint8Array | Uint8ClampedArray | Buffer;
14
14
  width: number;
15
15
  height: number;
@@ -156,6 +156,10 @@ declare function runComparison(received: ImageInput, baseline: ImageInput, metho
156
156
  * Check if input is a file path
157
157
  */
158
158
  declare function isFilePath(input: ImageInput): input is string;
159
+ /**
160
+ * Check if input is a raw PNG buffer (Buffer or Uint8Array without dimensions)
161
+ */
162
+ declare function isRawPngBuffer(input: ImageInput): input is Buffer | Uint8Array;
159
163
  /**
160
164
  * Check if input is an image buffer with dimensions
161
165
  */
@@ -174,8 +178,9 @@ declare function loadPNG(filePath: string): Promise<ImageData>;
174
178
  declare function savePNG(filePath: string, data: Uint8Array | Uint8ClampedArray | Buffer, width: number, height: number): Promise<void>;
175
179
  /**
176
180
  * Normalize image input to ImageData
177
- * If input is a file path, loads the image
178
- * If input is already a buffer, returns it with normalized Uint8Array
181
+ * - File path: loads the PNG
182
+ * - Raw PNG buffer: decodes to get dimensions
183
+ * - Buffer with dimensions: returns as-is with normalized Uint8Array
179
184
  */
180
185
  declare function normalizeImageInput(input: ImageInput): Promise<ImageData>;
181
186
  /**
@@ -208,4 +213,4 @@ declare function getOrCreateSnapshot(received: ImageInput, options: MatcherOptio
208
213
  */
209
214
  declare function compareImages(received: ImageInput, baseline: ImageInput, options: MatcherOptions): Promise<ComparisonResult>;
210
215
 
211
- export { type ComparisonMethod, type ComparisonResult, type FormatOptions, type ImageData, type ImageInput, type MatcherOptions, type TestContext, compareImages, fileExists, formatMessage as formatReport, getOrCreateSnapshot, isFilePath, isImageBuffer, loadPNG, normalizeImageInput, runComparison, savePNG, validateMethodSupportsInput };
216
+ export { type ComparisonMethod, type ComparisonResult, type FormatOptions, type ImageData, type ImageInput, type MatcherOptions, type TestContext, compareImages, fileExists, formatMessage as formatReport, getOrCreateSnapshot, isFilePath, isImageBuffer, isRawPngBuffer, loadPNG, normalizeImageInput, runComparison, savePNG, validateMethodSupportsInput };
package/dist/index.d.ts CHANGED
@@ -7,9 +7,9 @@ type ComparisonMethod = "bin" | "core" | "ssim" | "msssim" | "hitchhikers-ssim"
7
7
  */
8
8
  type SnapshotStatus = "added" | "matched" | "updated" | "failed";
9
9
  /**
10
- * Image input - either a file path or a buffer with dimensions
10
+ * Image input - file path, raw PNG buffer, or buffer with dimensions
11
11
  */
12
- type ImageInput = string | {
12
+ type ImageInput = string | Buffer | Uint8Array | {
13
13
  data: Uint8Array | Uint8ClampedArray | Buffer;
14
14
  width: number;
15
15
  height: number;
@@ -156,6 +156,10 @@ declare function runComparison(received: ImageInput, baseline: ImageInput, metho
156
156
  * Check if input is a file path
157
157
  */
158
158
  declare function isFilePath(input: ImageInput): input is string;
159
+ /**
160
+ * Check if input is a raw PNG buffer (Buffer or Uint8Array without dimensions)
161
+ */
162
+ declare function isRawPngBuffer(input: ImageInput): input is Buffer | Uint8Array;
159
163
  /**
160
164
  * Check if input is an image buffer with dimensions
161
165
  */
@@ -174,8 +178,9 @@ declare function loadPNG(filePath: string): Promise<ImageData>;
174
178
  declare function savePNG(filePath: string, data: Uint8Array | Uint8ClampedArray | Buffer, width: number, height: number): Promise<void>;
175
179
  /**
176
180
  * Normalize image input to ImageData
177
- * If input is a file path, loads the image
178
- * If input is already a buffer, returns it with normalized Uint8Array
181
+ * - File path: loads the PNG
182
+ * - Raw PNG buffer: decodes to get dimensions
183
+ * - Buffer with dimensions: returns as-is with normalized Uint8Array
179
184
  */
180
185
  declare function normalizeImageInput(input: ImageInput): Promise<ImageData>;
181
186
  /**
@@ -208,4 +213,4 @@ declare function getOrCreateSnapshot(received: ImageInput, options: MatcherOptio
208
213
  */
209
214
  declare function compareImages(received: ImageInput, baseline: ImageInput, options: MatcherOptions): Promise<ComparisonResult>;
210
215
 
211
- export { type ComparisonMethod, type ComparisonResult, type FormatOptions, type ImageData, type ImageInput, type MatcherOptions, type TestContext, compareImages, fileExists, formatMessage as formatReport, getOrCreateSnapshot, isFilePath, isImageBuffer, loadPNG, normalizeImageInput, runComparison, savePNG, validateMethodSupportsInput };
216
+ export { type ComparisonMethod, type ComparisonResult, type FormatOptions, type ImageData, type ImageInput, type MatcherOptions, type TestContext, compareImages, fileExists, formatMessage as formatReport, getOrCreateSnapshot, isFilePath, isImageBuffer, isRawPngBuffer, loadPNG, normalizeImageInput, runComparison, savePNG, validateMethodSupportsInput };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- 'use strict';var fs=require('fs'),path=require('path'),pngjsTransformer=require('@blazediff/pngjs-transformer'),bin=require('@blazediff/bin'),core=require('@blazediff/core'),gmsd=require('@blazediff/gmsd'),ssim=require('@blazediff/ssim'),hitchhikersSsim=require('@blazediff/ssim/hitchhikers-ssim'),msssim=require('@blazediff/ssim/msssim'),s=require('picocolors');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var s__default=/*#__PURE__*/_interopDefault(s);function c(t){return typeof t=="string"}function _(t){return typeof t=="object"&&t!==null&&"data"in t&&"width"in t&&"height"in t}async function w(t){if(!fs.existsSync(t))throw new Error(`Image file not found: ${t}`);let e=await pngjsTransformer.pngjsTransformer.read(t);return {data:new Uint8Array(e.data),width:e.width,height:e.height}}async function l(t,e,n,r){let o=path.dirname(t);fs.existsSync(o)||fs.mkdirSync(o,{recursive:true}),await pngjsTransformer.pngjsTransformer.write({data:e,width:n,height:r},t);}async function C(t){return c(t)?w(t):{data:new Uint8Array(t.data),width:t.width,height:t.height}}function D(t){return fs.existsSync(t)}function N(t){fs.existsSync(t)||fs.mkdirSync(t,{recursive:true});}async function T(t,e,n,r){if(!c(t))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");if(!c(e))throw new Error("Method 'bin' only supports file paths for baseline, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");let o=await bin.compare(t,e,n,{threshold:r.threshold,antialiasing:r.antialiasing});if(o.match)return {diffCount:0,diffPercentage:0};if(o.reason==="layout-diff")return {diffCount:Number.MAX_SAFE_INTEGER,diffPercentage:100};if(o.reason==="pixel-diff")return {diffCount:o.diffCount,diffPercentage:o.diffPercentage};if(o.reason==="file-not-exists")throw new Error(`Image file not found: ${o.file}`);return {diffCount:0,diffPercentage:0}}function E(t,e,n,r){let{width:o,height:i}=t,a=o*i;if(t.width!==e.width||t.height!==e.height)return {diffCount:a,diffPercentage:100};let m=n?new Uint8Array(a*4):void 0,u=core.diff(t.data,e.data,m,o,i,{threshold:r.threshold??.1,includeAA:r.includeAA??false});return {diffCount:u,diffPercentage:u/a*100,diffOutput:m}}function A(t,e,n,r){let{width:o,height:i}=t,a=o*i;if(t.width!==e.width||t.height!==e.height)return {score:1};let m=n?new Uint8Array(a*4):void 0;return {score:gmsd.gmsd(t.data,e.data,m,o,i,{downsample:r.downsample}),diffOutput:m}}function R(t,e,n,r,o){let{width:i,height:a}=t,m=i*a;if(t.width!==e.width||t.height!==e.height)return {score:0};let u=r?new Uint8Array(m*4):void 0,d={windowSize:o.windowSize,k1:o.k1,k2:o.k2},g;switch(n){case "ssim":g=ssim.ssim(t.data,e.data,u,i,a,d);break;case "msssim":g=msssim.msssim(t.data,e.data,u,i,a,d);break;case "hitchhikers-ssim":g=hitchhikersSsim.hitchhikersSSIM(t.data,e.data,u,i,a,d);break;default:throw new Error(`Unknown SSIM method: ${n}`)}return {score:g,diffOutput:u}}function I(t){return t==="ssim"||t==="msssim"||t==="hitchhikers-ssim"}function U(t,e){if(t==="bin"&&!c(e))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.")}async function S(t,e,n,r,o){if(U(n,t),U(n,e),n==="bin"){let d=await T(t,e,o,r);return {diffCount:d.diffCount,diffPercentage:d.diffPercentage}}let i=await C(t),a=await C(e),m=o!==void 0;if(I(n)){let d=R(i,a,n,m,r);return {score:d.score,diffOutput:d.diffOutput}}if(n==="gmsd"){let d=A(i,a,m,r);return {score:d.score,diffOutput:d.diffOutput}}let u=E(i,a,m,r);return {diffCount:u.diffCount,diffPercentage:u.diffPercentage,diffOutput:u.diffOutput}}var y={success:s__default.default.isColorSupported?"\u2714":"\u221A",error:s__default.default.isColorSupported?"\u2716":"\xD7",info:s__default.default.isColorSupported?"\u2139":"i",arrow:s__default.default.isColorSupported?"\u2514\u2500":"'-"},q=new Set(["ssim","msssim","hitchhikers-ssim"]);function P(t){return t.snapshotCreated?J(t.baselinePath):t.pass?K():Q(t)}function J(t){return [`${s__default.default.green(y.success)} ${s__default.default.green("New snapshot created")}`,` ${s__default.default.dim(y.arrow)} ${s__default.default.dim(t)}`].join(`
2
- `)}function K(){return `${s__default.default.green(y.success)} ${s__default.default.green("Image matches snapshot")}`}function Q(t){let{method:e,baselinePath:n,receivedPath:r,diffPath:o,diffCount:i=0,diffPercentage:a,score:m=0,threshold:u,thresholdType:d,updateCommand:g}=t,f=[`${s__default.default.red(y.error)} ${s__default.default.red(s__default.default.bold("Image snapshot mismatch"))}`,""],p=12;if(f.push(` ${s__default.default.dim("Method".padEnd(p))}${e}`),f.push(` ${s__default.default.dim("Baseline".padEnd(p))}${s__default.default.dim(n)}`),f.push(` ${s__default.default.dim("Received".padEnd(p))}${s__default.default.dim(r)}`),f.push(` ${s__default.default.dim("Diff".padEnd(p))}${s__default.default.dim(o)}`),f.push(""),q.has(e)){let h=((1-m)*100).toFixed(2);f.push(` ${s__default.default.dim("SSIM Score".padEnd(p))}${s__default.default.yellow(m.toFixed(4))} ${s__default.default.dim("(1.0 = identical)")}`),f.push(` ${s__default.default.dim("Difference".padEnd(p))}${s__default.default.yellow(`${h}%`)}`);}else if(e==="gmsd")f.push(` ${s__default.default.dim("GMSD Score".padEnd(p))}${s__default.default.yellow(m.toFixed(4))} ${s__default.default.dim("(0.0 = identical)")}`);else {let h=a?.toFixed(2)??"0.00";f.push(` ${s__default.default.dim("Difference".padEnd(p))}${s__default.default.yellow(i.toLocaleString())} pixels ${s__default.default.dim(`(${h}%)`)}`);}let k=d==="percent"?"%":"pixels";return f.push(` ${s__default.default.dim("Threshold".padEnd(p))}${u} ${k}`),f.push(""),f.push(` ${s__default.default.cyan(y.info)} ${s__default.default.cyan(`Run with ${g??"--update"} to update the snapshot`)}`),f.join(`
3
- `)}function v(t){return t.testName.replace(/[^a-zA-Z0-9-_\s]/g,"").replace(/\s+/g,"-").toLowerCase()||"snapshot"}function tt(t,e){let n=path.dirname(t.testPath),r=e.snapshotsDir??"__snapshots__",o=path.isAbsolute(r)?r:path.join(n,r),i=e.snapshotIdentifier??v(t);return {snapshotDir:o,baselinePath:path.join(o,`${i}.png`),receivedPath:path.join(o,`${i}.received.png`),diffPath:path.join(o,`${i}.diff.png`)}}function B(t,e,n){let r=n.failureThreshold??0,o=n.failureThresholdType??"pixel";if(I(t)){let i=e.score??0;return o==="percent"?(1-i)*100<=r:i>=1-r/100}if(t==="gmsd"){let i=e.score??0;return o==="percent"?i*100<=r:i<=r/100}return o==="percent"?(e.diffPercentage??0)<=r:(e.diffCount??0)<=r}async function et(t,e,n){let r=tt(n,e),{snapshotDir:o,baselinePath:i,receivedPath:a,diffPath:m}=r;N(o);let u=D(i),d=e.updateSnapshots===true?"all":e.updateSnapshots===false||e.updateSnapshots===void 0?"new":e.updateSnapshots;if(d!=="none"&&(u&&d==="all"||!u&&(d==="new"||d==="all"))){if(c(t)){let O=await w(t);await l(i,O.data,O.width,O.height);}else await l(i,t.data,t.width,t.height);return fs.existsSync(a)&&fs.unlinkSync(a),fs.existsSync(m)&&fs.unlinkSync(m),{pass:true,message:P({pass:true,method:e.method,snapshotCreated:true,baselinePath:i,receivedPath:a,diffPath:m,diffCount:0,diffPercentage:0,score:0,threshold:e.failureThreshold??0,thresholdType:e.failureThresholdType??"pixel",updateCommand:e.updateCommand}),baselinePath:i,snapshotStatus:u?"updated":"added"}}let f=await S(t,i,e.method,e,m),p=B(e.method,f,e);if(p)return fs.existsSync(a)&&fs.unlinkSync(a),fs.existsSync(m)&&fs.unlinkSync(m),{pass:true,message:P({pass:p,method:e.method,snapshotCreated:false,baselinePath:i,receivedPath:a,diffPath:m,diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,threshold:e.failureThreshold??0,thresholdType:e.failureThresholdType??"pixel",updateCommand:e.updateCommand}),diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,baselinePath:i,snapshotStatus:"matched"};if(c(t)){let h=await w(t);await l(a,h.data,h.width,h.height);}else await l(a,t.data,t.width,t.height);if(f.diffOutput){let h=await C(t);await l(m,f.diffOutput,h.width,h.height);}return {pass:false,message:P({pass:p,method:e.method,snapshotCreated:false,baselinePath:i,receivedPath:a,diffPath:m,diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,threshold:e.failureThreshold??0,thresholdType:e.failureThresholdType??"pixel",updateCommand:e.updateCommand}),diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,baselinePath:i,receivedPath:a,diffPath:m,snapshotStatus:"failed"}}async function rt(t,e,n){let r=await S(t,e,n.method,n),o=B(n.method,r,n);return {pass:o,message:o?"Images match.":`Images differ: ${r.diffCount??r.score} ${r.diffCount!==void 0?"pixels":"score"}`,diffCount:r.diffCount,diffPercentage:r.diffPercentage,score:r.score}}exports.compareImages=rt;exports.fileExists=D;exports.formatReport=P;exports.getOrCreateSnapshot=et;exports.isFilePath=c;exports.isImageBuffer=_;exports.loadPNG=w;exports.normalizeImageInput=C;exports.runComparison=S;exports.savePNG=l;exports.validateMethodSupportsInput=U;
1
+ 'use strict';var fs=require('fs'),path=require('path'),pngjsTransformer=require('@blazediff/pngjs-transformer'),bin=require('@blazediff/bin'),core=require('@blazediff/core'),gmsd=require('@blazediff/gmsd'),ssim=require('@blazediff/ssim'),hitchhikersSsim=require('@blazediff/ssim/hitchhikers-ssim'),msssim=require('@blazediff/ssim/msssim'),s=require('picocolors');function _interopDefault(e){return e&&e.__esModule?e:{default:e}}var s__default=/*#__PURE__*/_interopDefault(s);function c(e){return typeof e=="string"}function $(e){return (Buffer.isBuffer(e)||e instanceof Uint8Array)&&!("width"in e)}function j(e){return typeof e=="object"&&e!==null&&"data"in e&&"width"in e&&"height"in e}async function I(e){if(!fs.existsSync(e))throw new Error(`Image file not found: ${e}`);let t=await pngjsTransformer.pngjsTransformer.read(e);return {data:new Uint8Array(t.data),width:t.width,height:t.height}}async function l(e,t,o,a){let i=path.dirname(e);fs.existsSync(i)||fs.mkdirSync(i,{recursive:true}),await pngjsTransformer.pngjsTransformer.write({data:t,width:o,height:a},e);}async function w(e){if(c(e))return I(e);if($(e)){let t=Buffer.isBuffer(e)?e:Buffer.from(e),o=await pngjsTransformer.pngjsTransformer.read(t);return {data:new Uint8Array(o.data),width:o.width,height:o.height}}return {data:new Uint8Array(e.data),width:e.width,height:e.height}}function E(e){return fs.existsSync(e)}function z(e){fs.existsSync(e)||fs.mkdirSync(e,{recursive:true});}async function U(e,t,o,a){if(!c(e))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");if(!c(t))throw new Error("Method 'bin' only supports file paths for baseline, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");let i=await bin.compare(e,t,o,{threshold:a.threshold,antialiasing:a.antialiasing});if(i.match)return {diffCount:0,diffPercentage:0};if(i.reason==="layout-diff")return {diffCount:Number.MAX_SAFE_INTEGER,diffPercentage:100};if(i.reason==="pixel-diff")return {diffCount:i.diffCount,diffPercentage:i.diffPercentage};if(i.reason==="file-not-exists")throw new Error(`Image file not found: ${i.file}`);return {diffCount:0,diffPercentage:0}}function B(e,t,o,a){let{width:i,height:r}=e,f=i*r;if(e.width!==t.width||e.height!==t.height)return {diffCount:f,diffPercentage:100};let d=o?new Uint8Array(f*4):void 0,n=core.diff(e.data,t.data,d,i,r,{threshold:a.threshold??.1,includeAA:a.includeAA??false});return {diffCount:n,diffPercentage:n/f*100,diffOutput:d}}function k(e,t,o,a){let{width:i,height:r}=e,f=i*r;if(e.width!==t.width||e.height!==t.height)return {score:1};let d=o?new Uint8Array(f*4):void 0;return {score:gmsd.gmsd(e.data,t.data,d,i,r,{downsample:a.downsample}),diffOutput:d}}function F(e,t,o,a,i){let{width:r,height:f}=e,d=r*f;if(e.width!==t.width||e.height!==t.height)return {score:0};let n=a?new Uint8Array(d*4):void 0,u={windowSize:i.windowSize,k1:i.k1,k2:i.k2},p;switch(o){case "ssim":p=ssim.ssim(e.data,t.data,n,r,f,u);break;case "msssim":p=msssim.msssim(e.data,t.data,n,r,f,u);break;case "hitchhikers-ssim":p=hitchhikersSsim.hitchhikersSSIM(e.data,t.data,n,r,f,u);break;default:throw new Error(`Unknown SSIM method: ${o}`)}return {score:p,diffOutput:n}}function x(e){return e==="ssim"||e==="msssim"||e==="hitchhikers-ssim"}function G(e,t){if(e==="bin"&&!c(t))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.")}async function O(e,t,o,a,i){if(G(o,e),G(o,t),o==="bin"){let u=await U(e,t,i,a);return {diffCount:u.diffCount,diffPercentage:u.diffPercentage}}let r=await w(e),f=await w(t),d=i!==void 0;if(x(o)){let u=F(r,f,o,d,a);return {score:u.score,diffOutput:u.diffOutput}}if(o==="gmsd"){let u=k(r,f,d,a);return {score:u.score,diffOutput:u.diffOutput}}let n=B(r,f,d,a);return {diffCount:n.diffCount,diffPercentage:n.diffPercentage,diffOutput:n.diffOutput}}var S={success:s__default.default.isColorSupported?"\u2714":"\u221A",error:s__default.default.isColorSupported?"\u2716":"\xD7",info:s__default.default.isColorSupported?"\u2139":"i",arrow:s__default.default.isColorSupported?"\u2514\u2500":"'-"},J=new Set(["ssim","msssim","hitchhikers-ssim"]);function y(e){return e.snapshotCreated?K(e.baselinePath):e.pass?Q():V(e)}function K(e){return [`${s__default.default.green(S.success)} ${s__default.default.green("New snapshot created")}`,` ${s__default.default.dim(S.arrow)} ${s__default.default.dim(e)}`].join(`
2
+ `)}function Q(){return `${s__default.default.green(S.success)} ${s__default.default.green("Image matches snapshot")}`}function V(e){let{method:t,baselinePath:o,receivedPath:a,diffPath:i,diffCount:r=0,diffPercentage:f,score:d=0,threshold:n,thresholdType:u,updateCommand:p}=e,h=[`${s__default.default.red(S.error)} ${s__default.default.red(s__default.default.bold("Image snapshot mismatch"))}`,""],m=12;if(h.push(` ${s__default.default.dim("Method".padEnd(m))}${t}`),h.push(` ${s__default.default.dim("Baseline".padEnd(m))}${s__default.default.dim(o)}`),h.push(` ${s__default.default.dim("Received".padEnd(m))}${s__default.default.dim(a)}`),h.push(` ${s__default.default.dim("Diff".padEnd(m))}${s__default.default.dim(i)}`),h.push(""),J.has(t)){let b=((1-d)*100).toFixed(2);h.push(` ${s__default.default.dim("SSIM Score".padEnd(m))}${s__default.default.yellow(d.toFixed(4))} ${s__default.default.dim("(1.0 = identical)")}`),h.push(` ${s__default.default.dim("Difference".padEnd(m))}${s__default.default.yellow(`${b}%`)}`);}else if(t==="gmsd")h.push(` ${s__default.default.dim("GMSD Score".padEnd(m))}${s__default.default.yellow(d.toFixed(4))} ${s__default.default.dim("(0.0 = identical)")}`);else {let b=f?.toFixed(2)??"0.00";h.push(` ${s__default.default.dim("Difference".padEnd(m))}${s__default.default.yellow(r.toLocaleString())} pixels ${s__default.default.dim(`(${b}%)`)}`);}let P=u==="percent"?"%":"pixels";return h.push(` ${s__default.default.dim("Threshold".padEnd(m))}${n} ${P}`),h.push(""),h.push(` ${s__default.default.cyan(S.info)} ${s__default.default.cyan(`Run with ${p??"--update"} to update the snapshot`)}`),h.join(`
3
+ `)}function te(e){return e.testName.replace(/[^a-zA-Z0-9-_\s]/g,"").replace(/\s+/g,"-").toLowerCase()||"snapshot"}function re(e,t){let o=path.dirname(e.testPath),a=t.snapshotsDir??"__snapshots__",i=path.isAbsolute(a)?a:path.join(o,a),r=t.snapshotIdentifier??te(e);return {snapshotDir:i,baselinePath:path.join(i,`${r}.png`),receivedPath:path.join(i,`${r}.received.png`),diffPath:path.join(i,`${r}.diff.png`)}}function _(e,t,o){let a=o.failureThreshold??0,i=o.failureThresholdType??"pixel";if(x(e)){let r=t.score??0;return i==="percent"?(1-r)*100<=a:r>=1-a/100}if(e==="gmsd"){let r=t.score??0;return i==="percent"?r*100<=a:r<=a/100}return i==="percent"?(t.diffPercentage??0)<=a:(t.diffCount??0)<=a}async function ae(e,t,o){let a=re(o,t),{snapshotDir:i,baselinePath:r,receivedPath:f,diffPath:d}=a,n=$(e)?await w(e):e;z(i);let u=E(r),p=t.updateSnapshots===true?"all":t.updateSnapshots===false||t.updateSnapshots===void 0?"new":t.updateSnapshots;if(!u&&p!=="none"&&(p==="new"||p==="all")){if(c(n)){let C=await I(n);await l(r,C.data,C.width,C.height);}else await l(r,n.data,n.width,n.height);return {pass:true,message:y({pass:true,method:t.method,snapshotCreated:true,baselinePath:r,receivedPath:f,diffPath:d,diffCount:0,diffPercentage:0,score:0,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),baselinePath:r,snapshotStatus:"added"}}let m=await O(n,r,t.method,t,d),P=_(t.method,m,t);if(P)return fs.existsSync(f)&&fs.unlinkSync(f),fs.existsSync(d)&&fs.unlinkSync(d),{pass:true,message:y({pass:P,method:t.method,snapshotCreated:false,baselinePath:r,receivedPath:f,diffPath:d,diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,baselinePath:r,snapshotStatus:"matched"};if(p==="all"){if(c(n)){let C=await I(n);await l(r,C.data,C.width,C.height);}else await l(r,n.data,n.width,n.height);return fs.existsSync(f)&&fs.unlinkSync(f),fs.existsSync(d)&&fs.unlinkSync(d),{pass:true,message:y({pass:true,method:t.method,snapshotCreated:true,baselinePath:r,receivedPath:f,diffPath:d,diffCount:0,diffPercentage:0,score:0,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),baselinePath:r,snapshotStatus:"updated"}}if(c(n)){let g=await I(n);await l(f,g.data,g.width,g.height);}else await l(f,n.data,n.width,n.height);if(m.diffOutput){let g=await w(n);await l(d,m.diffOutput,g.width,g.height);}return {pass:false,message:y({pass:P,method:t.method,snapshotCreated:false,baselinePath:r,receivedPath:f,diffPath:d,diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,baselinePath:r,receivedPath:f,diffPath:d,snapshotStatus:"failed"}}async function ie(e,t,o){let a=await O(e,t,o.method,o),i=_(o.method,a,o);return {pass:i,message:i?"Images match.":`Images differ: ${a.diffCount??a.score} ${a.diffCount!==void 0?"pixels":"score"}`,diffCount:a.diffCount,diffPercentage:a.diffPercentage,score:a.score}}exports.compareImages=ie;exports.fileExists=E;exports.formatReport=y;exports.getOrCreateSnapshot=ae;exports.isFilePath=c;exports.isImageBuffer=j;exports.isRawPngBuffer=$;exports.loadPNG=I;exports.normalizeImageInput=w;exports.runComparison=O;exports.savePNG=l;exports.validateMethodSupportsInput=G;
package/dist/index.mjs CHANGED
@@ -1,3 +1,3 @@
1
- import {existsSync,mkdirSync,unlinkSync}from'fs';import {dirname,isAbsolute,join}from'path';import {pngjsTransformer}from'@blazediff/pngjs-transformer';import {compare}from'@blazediff/bin';import {diff}from'@blazediff/core';import {gmsd}from'@blazediff/gmsd';import {ssim}from'@blazediff/ssim';import {hitchhikersSSIM}from'@blazediff/ssim/hitchhikers-ssim';import {msssim}from'@blazediff/ssim/msssim';import s from'picocolors';function c(t){return typeof t=="string"}function _(t){return typeof t=="object"&&t!==null&&"data"in t&&"width"in t&&"height"in t}async function w(t){if(!existsSync(t))throw new Error(`Image file not found: ${t}`);let e=await pngjsTransformer.read(t);return {data:new Uint8Array(e.data),width:e.width,height:e.height}}async function l(t,e,n,r){let o=dirname(t);existsSync(o)||mkdirSync(o,{recursive:true}),await pngjsTransformer.write({data:e,width:n,height:r},t);}async function C(t){return c(t)?w(t):{data:new Uint8Array(t.data),width:t.width,height:t.height}}function D(t){return existsSync(t)}function N(t){existsSync(t)||mkdirSync(t,{recursive:true});}async function T(t,e,n,r){if(!c(t))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");if(!c(e))throw new Error("Method 'bin' only supports file paths for baseline, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");let o=await compare(t,e,n,{threshold:r.threshold,antialiasing:r.antialiasing});if(o.match)return {diffCount:0,diffPercentage:0};if(o.reason==="layout-diff")return {diffCount:Number.MAX_SAFE_INTEGER,diffPercentage:100};if(o.reason==="pixel-diff")return {diffCount:o.diffCount,diffPercentage:o.diffPercentage};if(o.reason==="file-not-exists")throw new Error(`Image file not found: ${o.file}`);return {diffCount:0,diffPercentage:0}}function E(t,e,n,r){let{width:o,height:i}=t,a=o*i;if(t.width!==e.width||t.height!==e.height)return {diffCount:a,diffPercentage:100};let m=n?new Uint8Array(a*4):void 0,u=diff(t.data,e.data,m,o,i,{threshold:r.threshold??.1,includeAA:r.includeAA??false});return {diffCount:u,diffPercentage:u/a*100,diffOutput:m}}function A(t,e,n,r){let{width:o,height:i}=t,a=o*i;if(t.width!==e.width||t.height!==e.height)return {score:1};let m=n?new Uint8Array(a*4):void 0;return {score:gmsd(t.data,e.data,m,o,i,{downsample:r.downsample}),diffOutput:m}}function R(t,e,n,r,o){let{width:i,height:a}=t,m=i*a;if(t.width!==e.width||t.height!==e.height)return {score:0};let u=r?new Uint8Array(m*4):void 0,d={windowSize:o.windowSize,k1:o.k1,k2:o.k2},g;switch(n){case "ssim":g=ssim(t.data,e.data,u,i,a,d);break;case "msssim":g=msssim(t.data,e.data,u,i,a,d);break;case "hitchhikers-ssim":g=hitchhikersSSIM(t.data,e.data,u,i,a,d);break;default:throw new Error(`Unknown SSIM method: ${n}`)}return {score:g,diffOutput:u}}function I(t){return t==="ssim"||t==="msssim"||t==="hitchhikers-ssim"}function U(t,e){if(t==="bin"&&!c(e))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.")}async function S(t,e,n,r,o){if(U(n,t),U(n,e),n==="bin"){let d=await T(t,e,o,r);return {diffCount:d.diffCount,diffPercentage:d.diffPercentage}}let i=await C(t),a=await C(e),m=o!==void 0;if(I(n)){let d=R(i,a,n,m,r);return {score:d.score,diffOutput:d.diffOutput}}if(n==="gmsd"){let d=A(i,a,m,r);return {score:d.score,diffOutput:d.diffOutput}}let u=E(i,a,m,r);return {diffCount:u.diffCount,diffPercentage:u.diffPercentage,diffOutput:u.diffOutput}}var y={success:s.isColorSupported?"\u2714":"\u221A",error:s.isColorSupported?"\u2716":"\xD7",info:s.isColorSupported?"\u2139":"i",arrow:s.isColorSupported?"\u2514\u2500":"'-"},q=new Set(["ssim","msssim","hitchhikers-ssim"]);function P(t){return t.snapshotCreated?J(t.baselinePath):t.pass?K():Q(t)}function J(t){return [`${s.green(y.success)} ${s.green("New snapshot created")}`,` ${s.dim(y.arrow)} ${s.dim(t)}`].join(`
2
- `)}function K(){return `${s.green(y.success)} ${s.green("Image matches snapshot")}`}function Q(t){let{method:e,baselinePath:n,receivedPath:r,diffPath:o,diffCount:i=0,diffPercentage:a,score:m=0,threshold:u,thresholdType:d,updateCommand:g}=t,f=[`${s.red(y.error)} ${s.red(s.bold("Image snapshot mismatch"))}`,""],p=12;if(f.push(` ${s.dim("Method".padEnd(p))}${e}`),f.push(` ${s.dim("Baseline".padEnd(p))}${s.dim(n)}`),f.push(` ${s.dim("Received".padEnd(p))}${s.dim(r)}`),f.push(` ${s.dim("Diff".padEnd(p))}${s.dim(o)}`),f.push(""),q.has(e)){let h=((1-m)*100).toFixed(2);f.push(` ${s.dim("SSIM Score".padEnd(p))}${s.yellow(m.toFixed(4))} ${s.dim("(1.0 = identical)")}`),f.push(` ${s.dim("Difference".padEnd(p))}${s.yellow(`${h}%`)}`);}else if(e==="gmsd")f.push(` ${s.dim("GMSD Score".padEnd(p))}${s.yellow(m.toFixed(4))} ${s.dim("(0.0 = identical)")}`);else {let h=a?.toFixed(2)??"0.00";f.push(` ${s.dim("Difference".padEnd(p))}${s.yellow(i.toLocaleString())} pixels ${s.dim(`(${h}%)`)}`);}let k=d==="percent"?"%":"pixels";return f.push(` ${s.dim("Threshold".padEnd(p))}${u} ${k}`),f.push(""),f.push(` ${s.cyan(y.info)} ${s.cyan(`Run with ${g??"--update"} to update the snapshot`)}`),f.join(`
3
- `)}function v(t){return t.testName.replace(/[^a-zA-Z0-9-_\s]/g,"").replace(/\s+/g,"-").toLowerCase()||"snapshot"}function tt(t,e){let n=dirname(t.testPath),r=e.snapshotsDir??"__snapshots__",o=isAbsolute(r)?r:join(n,r),i=e.snapshotIdentifier??v(t);return {snapshotDir:o,baselinePath:join(o,`${i}.png`),receivedPath:join(o,`${i}.received.png`),diffPath:join(o,`${i}.diff.png`)}}function B(t,e,n){let r=n.failureThreshold??0,o=n.failureThresholdType??"pixel";if(I(t)){let i=e.score??0;return o==="percent"?(1-i)*100<=r:i>=1-r/100}if(t==="gmsd"){let i=e.score??0;return o==="percent"?i*100<=r:i<=r/100}return o==="percent"?(e.diffPercentage??0)<=r:(e.diffCount??0)<=r}async function et(t,e,n){let r=tt(n,e),{snapshotDir:o,baselinePath:i,receivedPath:a,diffPath:m}=r;N(o);let u=D(i),d=e.updateSnapshots===true?"all":e.updateSnapshots===false||e.updateSnapshots===void 0?"new":e.updateSnapshots;if(d!=="none"&&(u&&d==="all"||!u&&(d==="new"||d==="all"))){if(c(t)){let O=await w(t);await l(i,O.data,O.width,O.height);}else await l(i,t.data,t.width,t.height);return existsSync(a)&&unlinkSync(a),existsSync(m)&&unlinkSync(m),{pass:true,message:P({pass:true,method:e.method,snapshotCreated:true,baselinePath:i,receivedPath:a,diffPath:m,diffCount:0,diffPercentage:0,score:0,threshold:e.failureThreshold??0,thresholdType:e.failureThresholdType??"pixel",updateCommand:e.updateCommand}),baselinePath:i,snapshotStatus:u?"updated":"added"}}let f=await S(t,i,e.method,e,m),p=B(e.method,f,e);if(p)return existsSync(a)&&unlinkSync(a),existsSync(m)&&unlinkSync(m),{pass:true,message:P({pass:p,method:e.method,snapshotCreated:false,baselinePath:i,receivedPath:a,diffPath:m,diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,threshold:e.failureThreshold??0,thresholdType:e.failureThresholdType??"pixel",updateCommand:e.updateCommand}),diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,baselinePath:i,snapshotStatus:"matched"};if(c(t)){let h=await w(t);await l(a,h.data,h.width,h.height);}else await l(a,t.data,t.width,t.height);if(f.diffOutput){let h=await C(t);await l(m,f.diffOutput,h.width,h.height);}return {pass:false,message:P({pass:p,method:e.method,snapshotCreated:false,baselinePath:i,receivedPath:a,diffPath:m,diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,threshold:e.failureThreshold??0,thresholdType:e.failureThresholdType??"pixel",updateCommand:e.updateCommand}),diffCount:f.diffCount,diffPercentage:f.diffPercentage,score:f.score,baselinePath:i,receivedPath:a,diffPath:m,snapshotStatus:"failed"}}async function rt(t,e,n){let r=await S(t,e,n.method,n),o=B(n.method,r,n);return {pass:o,message:o?"Images match.":`Images differ: ${r.diffCount??r.score} ${r.diffCount!==void 0?"pixels":"score"}`,diffCount:r.diffCount,diffPercentage:r.diffPercentage,score:r.score}}export{rt as compareImages,D as fileExists,P as formatReport,et as getOrCreateSnapshot,c as isFilePath,_ as isImageBuffer,w as loadPNG,C as normalizeImageInput,S as runComparison,l as savePNG,U as validateMethodSupportsInput};
1
+ import {existsSync,mkdirSync,unlinkSync}from'fs';import {dirname,isAbsolute,join}from'path';import {pngjsTransformer}from'@blazediff/pngjs-transformer';import {compare}from'@blazediff/bin';import {diff}from'@blazediff/core';import {gmsd}from'@blazediff/gmsd';import {ssim}from'@blazediff/ssim';import {hitchhikersSSIM}from'@blazediff/ssim/hitchhikers-ssim';import {msssim}from'@blazediff/ssim/msssim';import s from'picocolors';function c(e){return typeof e=="string"}function $(e){return (Buffer.isBuffer(e)||e instanceof Uint8Array)&&!("width"in e)}function j(e){return typeof e=="object"&&e!==null&&"data"in e&&"width"in e&&"height"in e}async function I(e){if(!existsSync(e))throw new Error(`Image file not found: ${e}`);let t=await pngjsTransformer.read(e);return {data:new Uint8Array(t.data),width:t.width,height:t.height}}async function l(e,t,o,a){let i=dirname(e);existsSync(i)||mkdirSync(i,{recursive:true}),await pngjsTransformer.write({data:t,width:o,height:a},e);}async function w(e){if(c(e))return I(e);if($(e)){let t=Buffer.isBuffer(e)?e:Buffer.from(e),o=await pngjsTransformer.read(t);return {data:new Uint8Array(o.data),width:o.width,height:o.height}}return {data:new Uint8Array(e.data),width:e.width,height:e.height}}function E(e){return existsSync(e)}function z(e){existsSync(e)||mkdirSync(e,{recursive:true});}async function U(e,t,o,a){if(!c(e))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");if(!c(t))throw new Error("Method 'bin' only supports file paths for baseline, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.");let i=await compare(e,t,o,{threshold:a.threshold,antialiasing:a.antialiasing});if(i.match)return {diffCount:0,diffPercentage:0};if(i.reason==="layout-diff")return {diffCount:Number.MAX_SAFE_INTEGER,diffPercentage:100};if(i.reason==="pixel-diff")return {diffCount:i.diffCount,diffPercentage:i.diffPercentage};if(i.reason==="file-not-exists")throw new Error(`Image file not found: ${i.file}`);return {diffCount:0,diffPercentage:0}}function B(e,t,o,a){let{width:i,height:r}=e,f=i*r;if(e.width!==t.width||e.height!==t.height)return {diffCount:f,diffPercentage:100};let d=o?new Uint8Array(f*4):void 0,n=diff(e.data,t.data,d,i,r,{threshold:a.threshold??.1,includeAA:a.includeAA??false});return {diffCount:n,diffPercentage:n/f*100,diffOutput:d}}function k(e,t,o,a){let{width:i,height:r}=e,f=i*r;if(e.width!==t.width||e.height!==t.height)return {score:1};let d=o?new Uint8Array(f*4):void 0;return {score:gmsd(e.data,t.data,d,i,r,{downsample:a.downsample}),diffOutput:d}}function F(e,t,o,a,i){let{width:r,height:f}=e,d=r*f;if(e.width!==t.width||e.height!==t.height)return {score:0};let n=a?new Uint8Array(d*4):void 0,u={windowSize:i.windowSize,k1:i.k1,k2:i.k2},p;switch(o){case "ssim":p=ssim(e.data,t.data,n,r,f,u);break;case "msssim":p=msssim(e.data,t.data,n,r,f,u);break;case "hitchhikers-ssim":p=hitchhikersSSIM(e.data,t.data,n,r,f,u);break;default:throw new Error(`Unknown SSIM method: ${o}`)}return {score:p,diffOutput:n}}function x(e){return e==="ssim"||e==="msssim"||e==="hitchhikers-ssim"}function G(e,t){if(e==="bin"&&!c(t))throw new Error("Method 'bin' only supports file paths, but received a buffer. Use method 'core', 'ssim', or 'gmsd' for buffer inputs.")}async function O(e,t,o,a,i){if(G(o,e),G(o,t),o==="bin"){let u=await U(e,t,i,a);return {diffCount:u.diffCount,diffPercentage:u.diffPercentage}}let r=await w(e),f=await w(t),d=i!==void 0;if(x(o)){let u=F(r,f,o,d,a);return {score:u.score,diffOutput:u.diffOutput}}if(o==="gmsd"){let u=k(r,f,d,a);return {score:u.score,diffOutput:u.diffOutput}}let n=B(r,f,d,a);return {diffCount:n.diffCount,diffPercentage:n.diffPercentage,diffOutput:n.diffOutput}}var S={success:s.isColorSupported?"\u2714":"\u221A",error:s.isColorSupported?"\u2716":"\xD7",info:s.isColorSupported?"\u2139":"i",arrow:s.isColorSupported?"\u2514\u2500":"'-"},J=new Set(["ssim","msssim","hitchhikers-ssim"]);function y(e){return e.snapshotCreated?K(e.baselinePath):e.pass?Q():V(e)}function K(e){return [`${s.green(S.success)} ${s.green("New snapshot created")}`,` ${s.dim(S.arrow)} ${s.dim(e)}`].join(`
2
+ `)}function Q(){return `${s.green(S.success)} ${s.green("Image matches snapshot")}`}function V(e){let{method:t,baselinePath:o,receivedPath:a,diffPath:i,diffCount:r=0,diffPercentage:f,score:d=0,threshold:n,thresholdType:u,updateCommand:p}=e,h=[`${s.red(S.error)} ${s.red(s.bold("Image snapshot mismatch"))}`,""],m=12;if(h.push(` ${s.dim("Method".padEnd(m))}${t}`),h.push(` ${s.dim("Baseline".padEnd(m))}${s.dim(o)}`),h.push(` ${s.dim("Received".padEnd(m))}${s.dim(a)}`),h.push(` ${s.dim("Diff".padEnd(m))}${s.dim(i)}`),h.push(""),J.has(t)){let b=((1-d)*100).toFixed(2);h.push(` ${s.dim("SSIM Score".padEnd(m))}${s.yellow(d.toFixed(4))} ${s.dim("(1.0 = identical)")}`),h.push(` ${s.dim("Difference".padEnd(m))}${s.yellow(`${b}%`)}`);}else if(t==="gmsd")h.push(` ${s.dim("GMSD Score".padEnd(m))}${s.yellow(d.toFixed(4))} ${s.dim("(0.0 = identical)")}`);else {let b=f?.toFixed(2)??"0.00";h.push(` ${s.dim("Difference".padEnd(m))}${s.yellow(r.toLocaleString())} pixels ${s.dim(`(${b}%)`)}`);}let P=u==="percent"?"%":"pixels";return h.push(` ${s.dim("Threshold".padEnd(m))}${n} ${P}`),h.push(""),h.push(` ${s.cyan(S.info)} ${s.cyan(`Run with ${p??"--update"} to update the snapshot`)}`),h.join(`
3
+ `)}function te(e){return e.testName.replace(/[^a-zA-Z0-9-_\s]/g,"").replace(/\s+/g,"-").toLowerCase()||"snapshot"}function re(e,t){let o=dirname(e.testPath),a=t.snapshotsDir??"__snapshots__",i=isAbsolute(a)?a:join(o,a),r=t.snapshotIdentifier??te(e);return {snapshotDir:i,baselinePath:join(i,`${r}.png`),receivedPath:join(i,`${r}.received.png`),diffPath:join(i,`${r}.diff.png`)}}function _(e,t,o){let a=o.failureThreshold??0,i=o.failureThresholdType??"pixel";if(x(e)){let r=t.score??0;return i==="percent"?(1-r)*100<=a:r>=1-a/100}if(e==="gmsd"){let r=t.score??0;return i==="percent"?r*100<=a:r<=a/100}return i==="percent"?(t.diffPercentage??0)<=a:(t.diffCount??0)<=a}async function ae(e,t,o){let a=re(o,t),{snapshotDir:i,baselinePath:r,receivedPath:f,diffPath:d}=a,n=$(e)?await w(e):e;z(i);let u=E(r),p=t.updateSnapshots===true?"all":t.updateSnapshots===false||t.updateSnapshots===void 0?"new":t.updateSnapshots;if(!u&&p!=="none"&&(p==="new"||p==="all")){if(c(n)){let C=await I(n);await l(r,C.data,C.width,C.height);}else await l(r,n.data,n.width,n.height);return {pass:true,message:y({pass:true,method:t.method,snapshotCreated:true,baselinePath:r,receivedPath:f,diffPath:d,diffCount:0,diffPercentage:0,score:0,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),baselinePath:r,snapshotStatus:"added"}}let m=await O(n,r,t.method,t,d),P=_(t.method,m,t);if(P)return existsSync(f)&&unlinkSync(f),existsSync(d)&&unlinkSync(d),{pass:true,message:y({pass:P,method:t.method,snapshotCreated:false,baselinePath:r,receivedPath:f,diffPath:d,diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,baselinePath:r,snapshotStatus:"matched"};if(p==="all"){if(c(n)){let C=await I(n);await l(r,C.data,C.width,C.height);}else await l(r,n.data,n.width,n.height);return existsSync(f)&&unlinkSync(f),existsSync(d)&&unlinkSync(d),{pass:true,message:y({pass:true,method:t.method,snapshotCreated:true,baselinePath:r,receivedPath:f,diffPath:d,diffCount:0,diffPercentage:0,score:0,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),baselinePath:r,snapshotStatus:"updated"}}if(c(n)){let g=await I(n);await l(f,g.data,g.width,g.height);}else await l(f,n.data,n.width,n.height);if(m.diffOutput){let g=await w(n);await l(d,m.diffOutput,g.width,g.height);}return {pass:false,message:y({pass:P,method:t.method,snapshotCreated:false,baselinePath:r,receivedPath:f,diffPath:d,diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,threshold:t.failureThreshold??0,thresholdType:t.failureThresholdType??"pixel",updateCommand:t.updateCommand}),diffCount:m.diffCount,diffPercentage:m.diffPercentage,score:m.score,baselinePath:r,receivedPath:f,diffPath:d,snapshotStatus:"failed"}}async function ie(e,t,o){let a=await O(e,t,o.method,o),i=_(o.method,a,o);return {pass:i,message:i?"Images match.":`Images differ: ${a.diffCount??a.score} ${a.diffCount!==void 0?"pixels":"score"}`,diffCount:a.diffCount,diffPercentage:a.diffPercentage,score:a.score}}export{ie as compareImages,E as fileExists,y as formatReport,ae as getOrCreateSnapshot,c as isFilePath,j as isImageBuffer,$ as isRawPngBuffer,I as loadPNG,w as normalizeImageInput,O as runComparison,l as savePNG,G as validateMethodSupportsInput};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@blazediff/matcher",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Core matcher logic for visual regression testing with blazediff",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -33,11 +33,11 @@
33
33
  "license": "MIT",
34
34
  "dependencies": {
35
35
  "picocolors": "^1.1.1",
36
- "@blazediff/bin": "3.1.0",
37
- "@blazediff/core": "1.9.0",
38
36
  "@blazediff/gmsd": "1.7.0",
39
- "@blazediff/ssim": "1.7.0",
40
- "@blazediff/pngjs-transformer": "2.1.0"
37
+ "@blazediff/core": "1.9.0",
38
+ "@blazediff/bin": "3.1.0",
39
+ "@blazediff/pngjs-transformer": "2.1.0",
40
+ "@blazediff/ssim": "1.7.0"
41
41
  },
42
42
  "devDependencies": {
43
43
  "@types/node": "^24.3.0",