@vizzly-testing/honeydiff 0.16.0 → 0.18.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/CHANGELOG.md CHANGED
@@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.18.0] - 2026-11-11
11
+
12
+ ### Added
13
+
14
+ - You know when one small tweak to a shared nav or footer shows up as a diff in every single
15
+ screenshot? Honeydiff can now spot those repeats for you. Pass `changeBlocks: true` to `compare`
16
+ and you'll get `difference.changeBlocks` back.
17
+
18
+ Each block groups nearby changed regions into what a person would call one change, then gives it
19
+ a `signature` based on its pixels instead of where it sits on the page. So the same change gets the
20
+ same signature on a short page, a tall page, or below a banner that pushed everything down. Group
21
+ by signature and you can review a repeated change once instead of fifty times.
22
+
23
+ Matching is exact on purpose. Two blocks only share a signature when every pixel in them is the
24
+ same, because a fuzzy match can't tell a one-letter edit apart from text that moved half a pixel.
25
+ The same edit on a different background, or right next to another change, gets its own signature.
26
+
27
+ It's off by default, since hashing a big changed area takes real time on full-page diffs. On a real
28
+ build with 148 changed screenshots it added about 4%, and leaving it off costs nothing at all.
29
+
30
+ **Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.17.0...v0.18.0
31
+
32
+ ## [0.17.0] - 2026-09-06
33
+
34
+ ### Added
35
+
36
+ - Added `HONEYDIFF_THREADS` and `configureThreads()` for one process-wide
37
+ Honeydiff compute budget.
38
+
39
+ ### Changed
40
+
41
+ - Reduced `analyze` CPU and temporary memory by sharing luminance and structural
42
+ metric work, with an exact-content fast path.
43
+
44
+ **Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.16.0...v0.17.0
45
+
10
46
  ## [0.16.0] - 2026-08-03
11
47
 
12
48
  ### Added
package/README.md CHANGED
@@ -56,6 +56,8 @@ pieces visual regression systems usually need once screenshots get real:
56
56
  - Variable-height screenshot support for full-page comparisons.
57
57
  - Diff, mask, and side-by-side image artifacts for debugging failures.
58
58
  - Exact region data, Delta E summaries, SSIM, MS-SSIM, GMSD, and diff fingerprints.
59
+ - Change blocks that identify each change by its pixels, so the same change matches across
60
+ screenshots at any position and page height.
59
61
  - WCAG contrast screening and color vision deficiency simulation.
60
62
  - Async and sync APIs with TypeScript definitions included.
61
63
 
@@ -130,6 +132,48 @@ console.log(result.perception.msSsim);
130
132
  console.log(result.perception.gmsd);
131
133
  ```
132
134
 
135
+ ### Bound CPU Usage
136
+
137
+ Use one process-wide limit when Honeydiff runs inside a worker service:
138
+
139
+ ```bash
140
+ HONEYDIFF_THREADS=4 node visual-tests.js
141
+ ```
142
+
143
+ Applications that cannot set the environment before startup can configure the
144
+ same limit before their first operation:
145
+
146
+ ```js
147
+ import { configureThreads } from '@vizzly-testing/honeydiff';
148
+
149
+ configureThreads(4);
150
+ ```
151
+
152
+ Repeating the same value is safe. Changing it after Honeydiff work starts
153
+ throws instead of silently creating an oversubscribed pool.
154
+
155
+ ### Find The Same Change Across Screenshots
156
+
157
+ ```js
158
+ let result = await compare('baseline.png', 'current.png', {
159
+ alignHeightChanges: true,
160
+ changeBlocks: true,
161
+ });
162
+
163
+ for (let block of result.difference.changeBlocks) {
164
+ console.log(block.signature, block.bounds);
165
+ }
166
+ ```
167
+
168
+ A block is a group of regions within 16px of each other, which is usually what a person would call
169
+ one change. Two blocks with the same `signature` have byte-identical baseline and current pixels in
170
+ their whole rectangle, wherever they sit on the page and however tall the page is. Group by
171
+ signature to review a repeated change once.
172
+
173
+ Matching is exact on purpose. The same edit on a different background, at a fractional position, or
174
+ next to another change within the gap gets a different signature. Only compare signatures whose
175
+ `cb1:` version prefix matches.
176
+
133
177
  ### Align One Added Or Removed Block
134
178
 
135
179
  ```js
@@ -178,8 +222,10 @@ await saveColorBlindnessSimulation(
178
222
  | `antialiasing` | `true` | Suppress conservative raster-coverage movement. |
179
223
  | `minimumRegionPixels` | `2` | Suppress smaller 8-connected visual regions. |
180
224
  | `alignHeightChanges` | `false` | Align one unambiguous inserted or removed row block. |
225
+ | `changeBlocks` | `false` | Merge nearby regions into blocks identified by their pixels. |
181
226
 
182
- There are no include flags. `compare` always returns its complete data.
227
+ `compare` always returns its complete data. `changeBlocks` is the one opt-in, because hashing a
228
+ large changed area adds real time to a full-page diff.
183
229
 
184
230
  ## Result Shape
185
231
 
package/index.d.ts CHANGED
@@ -77,6 +77,16 @@ export interface DiffRegion {
77
77
  appearance: DeltaESummary | null;
78
78
  }
79
79
 
80
+ export interface ChangeBlock {
81
+ /** Canvas-coordinate rectangle containing the merged regions. */
82
+ bounds: BoundingBox;
83
+ /**
84
+ * Exact identity of every baseline and current pixel in `bounds`, independent of position.
85
+ * Only compare signatures whose version prefix matches.
86
+ */
87
+ signature: string;
88
+ }
89
+
80
90
  export interface DiffAnalysis {
81
91
  different: boolean;
82
92
  settings: {
@@ -96,6 +106,8 @@ export interface DiffAnalysis {
96
106
  spatial: SpatialSummary | null;
97
107
  appearance: DeltaESummary | null;
98
108
  regions: DiffRegion[];
109
+ /** Present when the `changeBlocks` option is set. */
110
+ changeBlocks: ChangeBlock[] | null;
99
111
  };
100
112
  heightChange: {
101
113
  direction: 'added' | 'removed';
@@ -131,6 +143,8 @@ export interface CompareOptions {
131
143
  minimumRegionPixels?: number;
132
144
  /** Detect and align one unambiguous inserted or removed row block. Default: false. */
133
145
  alignHeightChanges?: boolean;
146
+ /** Merge nearby regions into blocks identified by their pixels. Default: false. */
147
+ changeBlocks?: boolean;
134
148
  }
135
149
 
136
150
  export interface ArtifactOutput {
@@ -143,6 +157,11 @@ export interface ArtifactOutput {
143
157
  }
144
158
 
145
159
  export const version: string;
160
+ /**
161
+ * Set one process-wide HoneyDiff compute budget before the first operation.
162
+ * Repeating the same value is safe; changing it after work starts throws.
163
+ */
164
+ export function configureThreads(threads: number): void;
146
165
  export function compare(
147
166
  baseline: ImageInput,
148
167
  current: ImageInput,
package/index.js CHANGED
@@ -42,6 +42,7 @@ export const imagesDiffer = addon.imagesDiffer;
42
42
  export const imagesDifferSync = addon.imagesDifferSync;
43
43
  export const analyze = addon.analyze;
44
44
  export const analyzeSync = addon.analyzeSync;
45
+ export const configureThreads = addon.configureThreads;
45
46
  export const getDimensions = addon.getDimensions;
46
47
  export const getDimensionsSync = addon.getDimensionsSync;
47
48
  export const version = packageMetadata.version;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vizzly-testing/honeydiff",
3
- "version": "0.16.0",
3
+ "version": "0.18.0",
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",