@vizzly-testing/honeydiff 0.10.1 โ†’ 0.10.3

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/CHANGELOG.md CHANGED
@@ -5,6 +5,28 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.10.3] - 2026-05-19
9
+
10
+ ## What's Changed
11
+
12
+ - โšก Speed up image comparison hot paths (#31)
13
+ - ๐Ÿ› ๏ธ Resume current npm release
14
+
15
+ **Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.10.2...v0.10.3
16
+
17
+ ## [0.10.2] - 2026-05-19
18
+
19
+ ## What's Changed
20
+
21
+ - ๐Ÿ› ๏ธ Remove release npm self-upgrade (#30)
22
+ - ๐Ÿ› ๏ธ Harden release workflows (#29)
23
+ - ๐Ÿงช Give coverage tests more time (#28)
24
+ - ๐Ÿ›ก๏ธ Harden honeydiff production contracts (#27)
25
+ - ๐Ÿ› Fix honeydiff-core clippy warnings
26
+ - ๐Ÿงช Add diff contract test suite
27
+
28
+ **Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.10.1...v0.10.2
29
+
8
30
  ## [0.10.1] - 2026-03-11
9
31
 
10
32
  ## What's Changed
package/README.md CHANGED
@@ -28,7 +28,7 @@ Built for production visual regression testing at scale.
28
28
  ### Basic Comparison
29
29
 
30
30
  ```javascript
31
- const { compare, quickCompare } = require('@vizzly-testing/honeydiff');
31
+ import { compare, quickCompare } from '@vizzly-testing/honeydiff';
32
32
 
33
33
  // Quick boolean check - are these images different?
34
34
  if (await quickCompare('baseline.png', 'current.png')) {
@@ -37,7 +37,7 @@ if (await quickCompare('baseline.png', 'current.png')) {
37
37
 
38
38
  // Detailed comparison with tolerance
39
39
  const result = await compare('baseline.png', 'current.png', {
40
- pixelTolerance: 10, // Ignore tiny differences
40
+ threshold: 10, // Ignore tiny differences
41
41
  includeSSIM: true // Perceptual similarity score
42
42
  });
43
43
 
@@ -52,7 +52,7 @@ console.log(`SSIM: ${result.perceptualScore}`);
52
52
  import { compare, CompareOptions, DiffResult } from '@vizzly-testing/honeydiff';
53
53
 
54
54
  const options: CompareOptions = {
55
- pixelTolerance: 5,
55
+ threshold: 5,
56
56
  includeSSIM: true,
57
57
  includeClusters: true
58
58
  };
@@ -79,14 +79,14 @@ test('homepage should match baseline', async () => {
79
79
 
80
80
  **Playwright**
81
81
  ```javascript
82
- const { compare } = require('@vizzly-testing/honeydiff');
82
+ import { compare } from '@vizzly-testing/honeydiff';
83
83
 
84
84
  test('button hover state', async () => {
85
85
  await page.hover('[data-testid="submit-button"]');
86
86
  let screenshot = await page.screenshot();
87
87
 
88
88
  let result = await compare('baseline.png', screenshot, {
89
- pixelTolerance: 10,
89
+ threshold: 10,
90
90
  diffPath: './artifacts/diff.png'
91
91
  });
92
92
 
@@ -256,26 +256,22 @@ GMSD is ideal for catching:
256
256
 
257
257
  **Reference:** Xue et al. 2014 - "Gradient Magnitude Similarity Deviation: A Highly Efficient Perceptual Image Quality Index"
258
258
 
259
- ### 7. Tolerance & Color Spaces
259
+ ### 7. Thresholds
260
260
 
261
- **RGB Mode (default)** - Exact matching with pixel tolerance:
262
- ```javascript
263
- const result = await compare('img1.png', 'img2.png', {
264
- pixelTolerance: 10 // Ignore differences below threshold (0-255)
265
- });
266
- ```
261
+ Honeydiff uses CIEDE2000 Delta E thresholds for perceptual color difference:
267
262
 
268
- **YIQ Mode** - Perceptual color matching weighted for human vision:
269
263
  ```javascript
270
264
  const result = await compare('img1.png', 'img2.png', {
271
- colorThreshold: 0.1 // YIQ mode (odiff-compatible)
265
+ threshold: 2.0 // Default: ignores tiny perceptual variance
272
266
  });
273
267
  ```
274
268
 
275
- **Brightness-only Mode** - Ignore color, compare structure:
269
+ Use exact mode when every changed pixel should count:
270
+
276
271
  ```javascript
277
272
  const result = await compare('img1.png', 'img2.png', {
278
- ignoreColors: true // Compare brightness/luminance only
273
+ threshold: 0,
274
+ minClusterSize: 1
279
275
  });
280
276
  ```
281
277
 
@@ -283,13 +279,15 @@ const result = await compare('img1.png', 'img2.png', {
283
279
 
284
280
  Work with in-memory images from screenshots or API responses.
285
281
 
282
+ For large screenshots, prefer file paths when possible. Buffer inputs are copied into the native worker before async processing begins, so path inputs put less pressure on the Node.js event loop and heap.
283
+
286
284
  ```javascript
287
- const fs = require('fs');
285
+ import fs from 'node:fs';
288
286
 
289
287
  // Compare buffers directly
290
288
  let img1 = fs.readFileSync('image1.png');
291
289
  let img2 = fs.readFileSync('image2.png');
292
- let result = await compare(img1, img2, { pixelTolerance: 5 });
290
+ let result = await compare(img1, img2, { threshold: 5 });
293
291
 
294
292
  // Mix paths and buffers
295
293
  let screenshot = await page.screenshot(); // Returns Buffer
@@ -301,7 +299,7 @@ let result = await compare('baseline.png', screenshot);
301
299
  Fast utility to get image dimensions without loading full image data.
302
300
 
303
301
  ```javascript
304
- const { getDimensions } = require('@vizzly-testing/honeydiff');
302
+ import { getDimensions } from '@vizzly-testing/honeydiff';
305
303
 
306
304
  let dims = await getDimensions('screenshot.png');
307
305
  console.log(`Image is ${dims.width}x${dims.height} pixels`);
@@ -317,7 +315,7 @@ let dims = await getDimensions(buffer);
317
315
  Get image dimensions, file size, and format detection - useful for storage tracking and billing.
318
316
 
319
317
  ```javascript
320
- const { getImageMetadata, getImageMetadataFromFile } = require('@vizzly-testing/honeydiff');
318
+ import { getImageMetadata, getImageMetadataFromFile } from '@vizzly-testing/honeydiff';
321
319
 
322
320
  // From buffer
323
321
  let buffer = fs.readFileSync('screenshot.png');
@@ -339,7 +337,12 @@ console.log(`${metadata.width}x${metadata.height}, ${metadata.fileSizeBytes} byt
339
337
  Group similar diffs across comparisons with fingerprinting. Perfect for batch-approving the same visual change that appears on multiple pages (e.g., header/footer updates).
340
338
 
341
339
  ```javascript
342
- const { compare, computeFingerprintSync, fingerprintSimilaritySync, fingerprintHashSync } = require('@vizzly-testing/honeydiff');
340
+ import {
341
+ compare,
342
+ computeFingerprintSync,
343
+ fingerprintSimilaritySync,
344
+ fingerprintHashSync
345
+ } from '@vizzly-testing/honeydiff';
343
346
 
344
347
  // Compare images with clustering enabled
345
348
  let result = await compare('baseline.png', 'current.png', {
@@ -406,7 +409,7 @@ Built-in WCAG color contrast analysis and color blindness simulation to catch ac
406
409
  Analyze entire images for WCAG color contrast violations - perfect for catching accessibility issues in screenshots and UI designs.
407
410
 
408
411
  ```javascript
409
- const { analyzeWcagContrast, saveWcagOverlay } = require('@vizzly-testing/honeydiff');
412
+ import { analyzeWcagContrast, saveWcagOverlay } from '@vizzly-testing/honeydiff';
410
413
 
411
414
  // Analyze a screenshot for accessibility violations
412
415
  let analysis = await analyzeWcagContrast('screenshot.png', {
@@ -461,12 +464,12 @@ Simulate how your UI appears to users with color vision deficiencies. Uses the s
461
464
  - `achromatopsia` - Complete color blindness (grayscale only)
462
465
 
463
466
  ```javascript
464
- const {
467
+ import {
465
468
  simulateColorBlindness,
466
469
  saveColorBlindnessSimulation,
467
470
  saveAllColorBlindnessSimulations,
468
471
  getColorBlindnessTypes
469
- } = require('@vizzly-testing/honeydiff');
472
+ } from '@vizzly-testing/honeydiff';
470
473
 
471
474
  // Get CVD type information
472
475
  let types = getColorBlindnessTypes();
@@ -492,7 +495,7 @@ await saveAllColorBlindnessSimulations('dashboard.png', 'dashboard', 'png');
492
495
  Analyze contrast accessibility specifically for colorblind users. This catches issues that only appear when colors are perceived differently.
493
496
 
494
497
  ```javascript
495
- const { analyzeWcagForCvd, analyzeWcagAllCvd } = require('@vizzly-testing/honeydiff');
498
+ import { analyzeWcagForCvd, analyzeWcagAllCvd } from '@vizzly-testing/honeydiff';
496
499
 
497
500
  // Analyze for a specific CVD type
498
501
  let analysis = await analyzeWcagForCvd('ui.png', 'deuteranopia', {
@@ -668,9 +671,8 @@ Benchmarked on 18.3M pixel screenshots (750 x 24,162 px):
668
671
 
669
672
  | Operation | Time | Throughput |
670
673
  |-----------|------|------------|
671
- | Basic RGB comparison | ~79ms | 231.8M pixels/sec |
674
+ | Basic CIEDE2000 comparison | ~79ms | 231.8M pixels/sec |
672
675
  | With anti-aliasing | ~88ms | 208M pixels/sec |
673
- | YIQ color space | ~89ms | 206M pixels/sec |
674
676
  | With artifacts (diff/mask/overlay) | ~432ms | 42.4M pixels/sec |
675
677
 
676
678
  **vs odiff:** 6.0x faster (79ms vs 474ms)
@@ -684,11 +686,11 @@ Multi-core parallelization: 215-309% CPU utilization across cores.
684
686
  ### CI/CD Integration
685
687
 
686
688
  ```javascript
687
- const { compare } = require('@vizzly-testing/honeydiff');
689
+ import { compare } from '@vizzly-testing/honeydiff';
688
690
 
689
691
  async function visualRegressionTest() {
690
692
  let result = await compare('baseline.png', 'current.png', {
691
- pixelTolerance: 10,
693
+ threshold: 10,
692
694
  maxDiffs: 1000, // Early exit for fast failure
693
695
  diffPath: process.env.CI ? './artifacts/diff.png' : undefined
694
696
  });
@@ -721,7 +723,7 @@ if (await quickCompare('baseline.png', 'current.png')) {
721
723
 
722
724
  ```javascript
723
725
  const result = await compare('baseline.png', 'current.png', {
724
- pixelTolerance: 10
726
+ threshold: 10
725
727
  });
726
728
 
727
729
  if (result.diffPercentage > 5.0) {
@@ -753,7 +755,7 @@ if (result.diffPercentage > 5.0) {
753
755
 
754
756
  **Anti-aliasing too aggressive**
755
757
  - Set `antialiasing: false` for stricter pixel matching
756
- - Adjust `pixelTolerance` instead for controlled flexibility
758
+ - Adjust `threshold` instead for controlled flexibility
757
759
 
758
760
  ## Use Cases
759
761
 
package/examples/basic.js CHANGED
@@ -1,32 +1,29 @@
1
1
  /**
2
- * Basic usage example for @honeydiff/node
2
+ * Basic usage example for @vizzly-testing/honeydiff
3
3
  */
4
4
 
5
5
  import * as honeydiff from '../index.js';
6
6
 
7
+ let baseline = '../../tests/fixtures/screenshots/vizzly-baseline.png';
8
+ let current = '../../tests/fixtures/screenshots/vizzly-with-diff.png';
9
+
7
10
  async function main() {
8
- console.log('Honeydiff Node.js Examples\n');
11
+ console.log('Honeydiff Node.js examples\n');
9
12
 
10
- // Example 1: Quick async comparison
11
- console.log('1. Quick comparison:');
12
- let isDifferent = await honeydiff.quickCompare(
13
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
14
- '../../tests/fixtures/screenshots/vizzly-with-diff.png'
15
- );
13
+ console.log('1. Quick comparison');
14
+ let isDifferent = await honeydiff.quickCompare(baseline, current);
16
15
  console.log(` Result: ${isDifferent ? 'DIFFERENT' : 'IDENTICAL'}\n`);
17
16
 
18
- // Example 2: Detailed async comparison
19
- console.log('2. Detailed comparison with options:');
20
- let result = await honeydiff.compare(
21
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
22
- '../../tests/fixtures/screenshots/vizzly-with-diff.png',
23
- {
24
- pixelTolerance: 0,
25
- antialiasing: true,
26
- includeSSIM: true,
27
- includeClusters: true,
28
- }
29
- );
17
+ console.log('2. Detailed comparison');
18
+ let result = await honeydiff.compare(baseline, current, {
19
+ threshold: 0,
20
+ antialiasing: true,
21
+ includeSSIM: true,
22
+ includeGMSD: true,
23
+ includeClusters: true,
24
+ includeDiffPixels: true,
25
+ minClusterSize: 1,
26
+ });
30
27
 
31
28
  console.log(` Diff percentage: ${result.diffPercentage.toFixed(2)}%`);
32
29
  console.log(` Different pixels: ${result.diffPixels} / ${result.totalPixels}`);
@@ -36,6 +33,10 @@ async function main() {
36
33
  console.log(` SSIM score: ${result.perceptualScore.toFixed(4)}`);
37
34
  }
38
35
 
36
+ if (result.gmsdScore !== null) {
37
+ console.log(` GMSD score: ${result.gmsdScore.toFixed(4)}`);
38
+ }
39
+
39
40
  if (result.boundingBox) {
40
41
  console.log(
41
42
  ` Bounding box: (${result.boundingBox.x}, ${result.boundingBox.y}) ${result.boundingBox.width}x${result.boundingBox.height}`
@@ -44,270 +45,34 @@ async function main() {
44
45
 
45
46
  if (result.diffClusters && result.diffClusters.length > 0) {
46
47
  console.log(` Found ${result.diffClusters.length} diff clusters`);
47
- result.diffClusters.slice(0, 3).forEach((cluster, i) => {
48
+ for (let [index, cluster] of result.diffClusters.slice(0, 3).entries()) {
48
49
  console.log(
49
- ` Cluster ${i + 1}: ${cluster.pixelCount} pixels at (${cluster.centerOfMass[0].toFixed(0)}, ${cluster.centerOfMass[1].toFixed(0)})`
50
+ ` Cluster ${index + 1}: ${cluster.pixelCount} pixels at (${cluster.centerOfMass[0].toFixed(0)}, ${cluster.centerOfMass[1].toFixed(0)})`
50
51
  );
51
- });
52
- }
53
-
54
- if (result.intensityStats) {
55
- console.log(` Intensity stats:`);
56
- console.log(` Range: ${result.intensityStats.min}-${result.intensityStats.max}`);
57
- console.log(
58
- ` Mean: ${result.intensityStats.mean.toFixed(1)}, Median: ${result.intensityStats.median}`
59
- );
60
- }
61
-
62
- console.log();
63
-
64
- // Example 3: Synchronous comparison (for when you need blocking behavior)
65
- console.log('3. Synchronous comparison:');
66
- let syncResult = honeydiff.compareSync(
67
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
68
- '../../tests/fixtures/screenshots/vizzly-with-diff.png',
69
- { pixelTolerance: 10 }
70
- );
71
- console.log(` Diff percentage: ${syncResult.diffPercentage.toFixed(2)}%`);
72
- console.log();
73
-
74
- // Example 4: Get image dimensions
75
- console.log('4. Get image dimensions:');
76
- let dimensions = await honeydiff.getDimensions(
77
- '../../tests/fixtures/screenshots/vizzly-baseline.png'
78
- );
79
- console.log(` Dimensions: ${dimensions.width}x${dimensions.height} pixels`);
80
- console.log();
81
-
82
- // Example 5: Get dimensions synchronously
83
- console.log('5. Get dimensions (sync):');
84
- let syncDimensions = honeydiff.getDimensionsSync(
85
- '../../tests/fixtures/screenshots/vizzly-with-diff.png'
86
- );
87
- console.log(` Dimensions: ${syncDimensions.width}x${syncDimensions.height} pixels`);
88
- console.log();
89
-
90
- // Example 6: Generate diff artifacts
91
- console.log('6. Generate diff artifacts:');
92
- let artifactResult = await honeydiff.compare(
93
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
94
- '../../tests/fixtures/screenshots/vizzly-with-diff.png',
95
- {
96
- diffPath: '/tmp/honeydiff-diff.png',
97
- maskPath: '/tmp/honeydiff-mask.png',
98
- overlayPath: '/tmp/honeydiff-overlay.png',
99
- overwrite: true,
100
- }
101
- );
102
- console.log(` Diff percentage: ${artifactResult.diffPercentage.toFixed(2)}%`);
103
- console.log(` Artifacts saved to /tmp/honeydiff-*.png`);
104
- console.log();
105
-
106
- // Example 7: Accessibility metadata tests
107
- console.log('7. Accessibility metadata (RGB + luminance + WCAG):');
108
- let accessibilityResult = await honeydiff.compare(
109
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
110
- '../../tests/fixtures/screenshots/vizzly-with-diff.png',
111
- {
112
- includeClusters: true,
113
- includeAccessibilityData: true,
114
- }
115
- );
116
-
117
- // Validate accessibility data is present
118
- if (!accessibilityResult.diffClusters || accessibilityResult.diffClusters.length === 0) {
119
- throw new Error('Test failed: Expected diff clusters to be present');
120
- }
121
-
122
- let firstCluster = accessibilityResult.diffClusters[0];
123
- if (!firstCluster.accessibilityMetadata) {
124
- throw new Error('Test failed: Expected accessibilityMetadata to be present');
125
- }
126
-
127
- let meta = firstCluster.accessibilityMetadata;
128
-
129
- // Validate RGB channel differences
130
- if (typeof meta.avgRDiff !== 'number' || meta.avgRDiff < 0) {
131
- throw new Error('Test failed: avgRDiff should be a non-negative number');
132
- }
133
- if (typeof meta.avgGDiff !== 'number' || meta.avgGDiff < 0) {
134
- throw new Error('Test failed: avgGDiff should be a non-negative number');
135
- }
136
- if (typeof meta.avgBDiff !== 'number' || meta.avgBDiff < 0) {
137
- throw new Error('Test failed: avgBDiff should be a non-negative number');
138
- }
139
-
140
- // Validate dominant channel
141
- if (!['R', 'G', 'B'].includes(meta.dominantChannel)) {
142
- throw new Error(
143
- `Test failed: dominantChannel should be R, G, or B, got ${meta.dominantChannel}`
144
- );
145
- }
146
-
147
- // Validate luminance values (0.0-1.0 range)
148
- if (meta.avgBaselineLuminance < 0 || meta.avgBaselineLuminance > 1) {
149
- throw new Error('Test failed: avgBaselineLuminance should be between 0 and 1');
150
- }
151
- if (meta.avgCurrentLuminance < 0 || meta.avgCurrentLuminance > 1) {
152
- throw new Error('Test failed: avgCurrentLuminance should be between 0 and 1');
153
- }
154
-
155
- // Validate contrast ratios (1.0-21.0 range)
156
- if (meta.contrastRatio < 1 || meta.contrastRatio > 21) {
157
- throw new Error('Test failed: contrastRatio should be between 1 and 21');
158
- }
159
- if (meta.minContrastRatio < 1 || meta.minContrastRatio > 21) {
160
- throw new Error('Test failed: minContrastRatio should be between 1 and 21');
161
- }
162
- if (meta.maxContrastRatio < 1 || meta.maxContrastRatio > 21) {
163
- throw new Error('Test failed: maxContrastRatio should be between 1 and 21');
164
- }
165
- if (meta.minContrastRatio > meta.maxContrastRatio) {
166
- throw new Error('Test failed: minContrastRatio should be <= maxContrastRatio');
167
- }
168
-
169
- // Validate colorBlindnessImpact is null when not requested
170
- if (meta.colorBlindnessImpact !== null) {
171
- throw new Error(
172
- 'Test failed: colorBlindnessImpact should be null when checkColorBlindness is not enabled'
173
- );
174
- }
175
-
176
- console.log(
177
- ` RGB diffs: R=${meta.avgRDiff.toFixed(1)}, G=${meta.avgGDiff.toFixed(1)}, B=${meta.avgBDiff.toFixed(1)}`
178
- );
179
- console.log(` Dominant channel: ${meta.dominantChannel}`);
180
- console.log(
181
- ` Luminance: baseline=${meta.avgBaselineLuminance.toFixed(3)}, current=${meta.avgCurrentLuminance.toFixed(3)}`
182
- );
183
- console.log(
184
- ` WCAG contrast: ${meta.contrastRatio.toFixed(2)}:1 (range: ${meta.minContrastRatio.toFixed(2)}-${meta.maxContrastRatio.toFixed(2)})`
185
- );
186
- console.log(' All accessibility metadata tests passed!');
187
- console.log();
188
-
189
- // Example 8: Color blindness checking tests
190
- console.log('8. Color blindness checking:');
191
- let cbResult = await honeydiff.compare(
192
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
193
- '../../tests/fixtures/screenshots/vizzly-with-diff.png',
194
- {
195
- includeClusters: true,
196
- checkColorBlindness: true,
197
- colorBlindnessThreshold: 30.0,
198
52
  }
199
- );
200
-
201
- // Validate clusters and accessibility data
202
- if (!cbResult.diffClusters || cbResult.diffClusters.length === 0) {
203
- throw new Error('Test failed: Expected diff clusters to be present');
204
- }
205
-
206
- let cbCluster = cbResult.diffClusters[0];
207
- if (!cbCluster.accessibilityMetadata) {
208
- throw new Error(
209
- 'Test failed: Expected accessibilityMetadata to be present when checkColorBlindness is enabled'
210
- );
211
- }
212
-
213
- let cbMeta = cbCluster.accessibilityMetadata;
214
-
215
- // Validate colorBlindnessImpact is present
216
- if (!cbMeta.colorBlindnessImpact) {
217
- throw new Error(
218
- 'Test failed: Expected colorBlindnessImpact to be present when checkColorBlindness is enabled'
219
- );
220
- }
221
-
222
- let impact = cbMeta.colorBlindnessImpact;
223
-
224
- // Validate boolean flags
225
- if (typeof impact.deuteranopiaVisible !== 'boolean') {
226
- throw new Error('Test failed: deuteranopiaVisible should be a boolean');
227
- }
228
- if (typeof impact.protanopiaVisible !== 'boolean') {
229
- throw new Error('Test failed: protanopiaVisible should be a boolean');
230
- }
231
- if (typeof impact.tritanopiaVisible !== 'boolean') {
232
- throw new Error('Test failed: tritanopiaVisible should be a boolean');
233
- }
234
- if (typeof impact.achromatopsiaVisible !== 'boolean') {
235
- throw new Error('Test failed: achromatopsiaVisible should be a boolean');
236
- }
237
-
238
- // Validate visibility score (0.0-1.0 range)
239
- if (impact.visibilityScore < 0 || impact.visibilityScore > 1) {
240
- throw new Error('Test failed: visibilityScore should be between 0 and 1');
241
53
  }
242
54
 
243
- console.log(` Visibility score: ${(impact.visibilityScore * 100).toFixed(0)}%`);
244
- console.log(` Deuteranopia visible: ${impact.deuteranopiaVisible}`);
245
- console.log(` Protanopia visible: ${impact.protanopiaVisible}`);
246
- console.log(` Tritanopia visible: ${impact.tritanopiaVisible}`);
247
- console.log(` Achromatopsia visible: ${impact.achromatopsiaVisible}`);
248
- console.log(' All color blindness tests passed!');
249
- console.log();
250
-
251
- // Example 9: Test checkColorBlindness automatically enables includeAccessibilityData
252
- console.log('9. Auto-enable test (checkColorBlindness enables includeAccessibilityData):');
253
- let autoEnableResult = await honeydiff.compare(
254
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
255
- '../../tests/fixtures/screenshots/vizzly-with-diff.png',
256
- {
257
- includeClusters: true,
258
- checkColorBlindness: true,
259
- // Note: NOT explicitly setting includeAccessibilityData
260
- }
261
- );
262
-
263
- if (!autoEnableResult.diffClusters || autoEnableResult.diffClusters.length === 0) {
264
- throw new Error('Test failed: Expected diff clusters to be present');
265
- }
266
-
267
- let autoCluster = autoEnableResult.diffClusters[0];
268
- if (!autoCluster.accessibilityMetadata) {
269
- throw new Error(
270
- 'Test failed: checkColorBlindness should automatically enable accessibilityMetadata'
271
- );
272
- }
273
-
274
- // Should have both accessibility data and color blindness impact
275
- if (!autoCluster.accessibilityMetadata.colorBlindnessImpact) {
276
- throw new Error(
277
- 'Test failed: Expected colorBlindnessImpact when checkColorBlindness is enabled'
278
- );
279
- }
280
-
281
- console.log(' Accessibility metadata auto-enabled: Yes');
282
- console.log(' Color blindness data present: Yes');
283
- console.log(' Auto-enable test passed!');
284
- console.log();
285
-
286
- // Example 10: Test accessibility data is null when not requested
287
- console.log('10. Null handling test (accessibility data absent when not requested):');
288
- let noAccessibilityResult = await honeydiff.compare(
289
- '../../tests/fixtures/screenshots/vizzly-baseline.png',
290
- '../../tests/fixtures/screenshots/vizzly-with-diff.png',
291
- {
292
- includeClusters: true,
293
- // Note: NOT setting includeAccessibilityData or checkColorBlindness
294
- }
295
- );
296
-
297
- if (!noAccessibilityResult.diffClusters || noAccessibilityResult.diffClusters.length === 0) {
298
- throw new Error('Test failed: Expected diff clusters to be present');
299
- }
300
-
301
- let noAccessCluster = noAccessibilityResult.diffClusters[0];
302
- if (noAccessCluster.accessibilityMetadata !== null) {
303
- throw new Error('Test failed: accessibilityMetadata should be null when not requested');
304
- }
305
-
306
- console.log(' Accessibility metadata: null (as expected)');
307
- console.log(' Null handling test passed!');
308
- console.log();
55
+ console.log('\n3. Synchronous comparison');
56
+ let syncResult = honeydiff.compareSync(baseline, current, {
57
+ threshold: 2,
58
+ includeClusters: true,
59
+ });
60
+ console.log(` Diff percentage: ${syncResult.diffPercentage.toFixed(2)}%`);
309
61
 
310
- console.log('=== All accessibility binding tests passed! ===\n');
62
+ console.log('\n4. Image dimensions');
63
+ let dimensions = await honeydiff.getDimensions(baseline);
64
+ console.log(` Dimensions: ${dimensions.width}x${dimensions.height}`);
65
+
66
+ console.log('\n5. Diff artifacts');
67
+ let artifactResult = await honeydiff.compare(baseline, current, {
68
+ threshold: 0,
69
+ diffPath: '/tmp/honeydiff-diff.png',
70
+ maskPath: '/tmp/honeydiff-mask.png',
71
+ overlayPath: '/tmp/honeydiff-side-by-side.png',
72
+ overwrite: true,
73
+ });
74
+ console.log(` Artifact diff percentage: ${artifactResult.diffPercentage.toFixed(2)}%`);
75
+ console.log(' Artifacts saved to /tmp/honeydiff-*.png');
311
76
  }
312
77
 
313
78
  main().catch((err) => {
@@ -16,7 +16,7 @@ async function main() {
16
16
 
17
17
  // Compare using buffers
18
18
  let result = await honeydiff.compare(img1Buffer, img2Buffer, {
19
- pixelTolerance: 0,
19
+ threshold: 0,
20
20
  includeSSIM: true,
21
21
  });
22
22
 
@@ -16,7 +16,7 @@ async function main(): Promise<void> {
16
16
 
17
17
  // Detailed comparison with full typing
18
18
  let options: CompareOptions = {
19
- pixelTolerance: 5,
19
+ threshold: 2,
20
20
  antialiasing: true,
21
21
  includeSSIM: true,
22
22
  includeClusters: true,
package/examples/wcag.js CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  import path from 'node:path';
9
9
  import { fileURLToPath } from 'node:url';
10
- import { analyzeWcagContrast, saveWcagOverlay } from '../index.js';
10
+ import { analyzeWcagContrast, analyzeWcagContrastSync, saveWcagOverlay } from '../index.js';
11
11
 
12
12
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
13
13
 
@@ -102,8 +102,6 @@ async function main() {
102
102
  // Example 4: Synchronous API (for simple scripts)
103
103
  console.log('4. Using synchronous API...');
104
104
  try {
105
- const { analyzeWcagContrastSync } = require('../index.js');
106
-
107
105
  let analysis = analyzeWcagContrastSync(
108
106
  path.join(__dirname, '../../../tests/fixtures/screenshots/vizzly-baseline.png'),
109
107
  {
package/index.d.ts CHANGED
@@ -187,7 +187,6 @@ export interface CompareOptions {
187
187
 
188
188
  /**
189
189
  * Include clustered groups of connected differing pixels
190
- * Automatically enables includeDiffPixels if not already enabled
191
190
  * Clusters are sorted by size (largest first)
192
191
  * @default false
193
192
  */
@@ -316,6 +315,8 @@ export type ImageInput = string | Buffer;
316
315
 
317
316
  /**
318
317
  * Compare two images asynchronously (recommended)
318
+ * For large screenshots, prefer file path inputs. Buffer inputs are copied
319
+ * before native worker processing begins.
319
320
  *
320
321
  * @param img1 - First image (file path or Buffer)
321
322
  * @param img2 - Second image (file path or Buffer)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizzly-testing/honeydiff",
3
- "version": "0.10.1",
3
+ "version": "0.10.3",
4
4
  "description": "High-performance image diffing for Node.js - Native bindings to Honeydiff Rust library",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "repository": {
30
30
  "type": "git",
31
- "url": "https://github.com/vizzly-testing/honeydiff"
31
+ "url": "https://github.com/vizzly-testing/r-honeydiff"
32
32
  },
33
33
  "keywords": [
34
34
  "image",