@vizzly-testing/honeydiff 0.13.1 → 0.15.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 +27 -4
- package/README.md +46 -4
- package/index.d.ts +52 -5
- package/package.json +1 -1
- package/platforms/index-aarch64-apple-darwin.node +0 -0
- package/platforms/index-aarch64-unknown-linux-gnu.node +0 -0
- package/platforms/index-x86_64-pc-windows-msvc.node +0 -0
- package/platforms/index-x86_64-unknown-linux-gnu.node +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.15.0] - 2026-08-03
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- ✨ Improve diffs for single-block height shifts (#39)
|
|
15
|
+
|
|
16
|
+
**Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.14.0...v0.15.0
|
|
17
|
+
|
|
18
|
+
## [0.14.0] - 2026-07-24
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
- Added opt-in, versioned `diffMaskEvidence` with a native analysis
|
|
22
|
+
identity, bitmap dimensions, completeness, and exact 8-connected component
|
|
23
|
+
facts derived from the retained pixels used by mask artifacts.
|
|
24
|
+
|
|
25
|
+
### Changed
|
|
26
|
+
- Named retained mask facts consistently around Honeydiff's diff-mask artifact:
|
|
27
|
+
`diffMaskPixels`, `diffMaskComplete`, `diffMaskEvidence`, and
|
|
28
|
+
`includeDiffMaskEvidence`.
|
|
29
|
+
- Diff-mask artifact generation reuses requested native evidence instead
|
|
30
|
+
of repeating the comparison to recover filtered coordinates.
|
|
31
|
+
|
|
32
|
+
**Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.13.1...v0.14.0
|
|
33
|
+
|
|
10
34
|
## [0.13.1] - 2026-07-23
|
|
11
35
|
|
|
12
36
|
### Changed
|
|
@@ -18,14 +42,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
18
42
|
## [0.13.0] - 2026-07-23
|
|
19
43
|
|
|
20
44
|
### Added
|
|
21
|
-
- Exposed
|
|
22
|
-
|
|
23
|
-
mask consumers.
|
|
45
|
+
- Exposed retained mask pixel count, completeness, semantics version, and the
|
|
46
|
+
installed package version for auditable mask consumers.
|
|
24
47
|
|
|
25
48
|
### Fixed
|
|
26
49
|
- Kept binary mask alpha opaque even when a transparent display diff color is
|
|
27
50
|
requested.
|
|
28
|
-
- Kept requested pixel and cluster diagnostics from changing the
|
|
51
|
+
- Kept requested pixel and cluster diagnostics from changing the diff mask
|
|
29
52
|
or variable-height classification.
|
|
30
53
|
|
|
31
54
|
**Full Changelog**: https://github.com/vizzly-testing/honeydiff/compare/v0.12.0...v0.13.0
|
package/README.md
CHANGED
|
@@ -121,6 +121,25 @@ for (let cluster of result.diffClusters ?? []) {
|
|
|
121
121
|
}
|
|
122
122
|
```
|
|
123
123
|
|
|
124
|
+
### Persist Authoritative Mask Evidence
|
|
125
|
+
|
|
126
|
+
Use diff-mask evidence when another system needs durable spatial facts
|
|
127
|
+
without decoding the generated PNG:
|
|
128
|
+
|
|
129
|
+
```js
|
|
130
|
+
let result = await compare('baseline.png', 'current.png', {
|
|
131
|
+
includeDiffMaskEvidence: true,
|
|
132
|
+
maskPath: 'artifacts/mask.png',
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
console.log(result.diffMaskEvidence?.analysisContractHash);
|
|
136
|
+
console.log(result.diffMaskEvidence?.components);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The components are exact 8-connected groups of retained mask pixels. They are
|
|
140
|
+
separate from `diffClusters`, whose optional merge heuristics are intended for
|
|
141
|
+
diagnostic presentation.
|
|
142
|
+
|
|
124
143
|
### Add Perceptual Metrics
|
|
125
144
|
|
|
126
145
|
```js
|
|
@@ -135,6 +154,23 @@ console.log(result.perceptualScore);
|
|
|
135
154
|
console.log(result.gmsdScore);
|
|
136
155
|
```
|
|
137
156
|
|
|
157
|
+
### Align One Added Or Removed Block
|
|
158
|
+
|
|
159
|
+
```js
|
|
160
|
+
let result = await compare('baseline.png', 'current.png', {
|
|
161
|
+
alignHeightChanges: true,
|
|
162
|
+
maskPath: 'artifacts/mask.png',
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
This opt-in handles one exact added or removed block of rows, such as a banner,
|
|
167
|
+
while keeping separate changes below it visible. Ambiguous matches,
|
|
168
|
+
bottom-only growth, and comparisons using `maxDiffs` use the normal comparison.
|
|
169
|
+
It does not handle multiple blocks, partial-width movement, or fuzzy matching.
|
|
170
|
+
An accepted comparison temporarily uses one additional RGBA frame. SSIM and
|
|
171
|
+
GMSD compare the unaligned overlapping portions, and the side-by-side overlay
|
|
172
|
+
uses the original images.
|
|
173
|
+
|
|
138
174
|
### Screenshot Contrast
|
|
139
175
|
|
|
140
176
|
```js
|
|
@@ -167,9 +203,11 @@ await saveColorBlindnessSimulation(
|
|
|
167
203
|
| --- | --- | --- |
|
|
168
204
|
| `threshold` | `2.0` | CIEDE2000 Delta E threshold. Use `0` for zero perceptual tolerance. |
|
|
169
205
|
| `antialiasing` | `true` | Ignore likely anti-aliased pixels. |
|
|
206
|
+
| `alignHeightChanges` | `false` | Align one conservatively detected added or removed block of rows. |
|
|
170
207
|
| `maxDiffs` | unlimited | Stop after a maximum number of differing pixels. Capped results classify from the pixels observed before early exit, without cluster filtering. |
|
|
171
208
|
| `includeDiffPixels` | `false` | Return individual differing pixel positions and intensities. |
|
|
172
209
|
| `includeClusters` | `false` | Return connected regions of visual change. |
|
|
210
|
+
| `includeDiffMaskEvidence` | `false` | Return authoritative diff-mask identity, dimensions, and exact components. |
|
|
173
211
|
| `minClusterSize` | `2` | Filter tiny isolated clusters as noise. |
|
|
174
212
|
| `clusterMerge` | disabled | Merge nearby clusters into logical text-like regions. |
|
|
175
213
|
| `includeSSIM` | `false` | Calculate structural similarity. More expensive on large images. |
|
|
@@ -187,9 +225,10 @@ interface DiffResult {
|
|
|
187
225
|
diffPercentage: number;
|
|
188
226
|
totalPixels: number;
|
|
189
227
|
diffPixels: number;
|
|
190
|
-
|
|
191
|
-
|
|
228
|
+
diffMaskPixels: number;
|
|
229
|
+
diffMaskComplete: boolean;
|
|
192
230
|
maskSemanticsVersion: string;
|
|
231
|
+
diffMaskEvidence: DiffMaskEvidence | null;
|
|
193
232
|
aaPixelsIgnored: number;
|
|
194
233
|
aaPercentage: number;
|
|
195
234
|
boundingBox: BoundingBox | null;
|
|
@@ -203,11 +242,14 @@ interface DiffResult {
|
|
|
203
242
|
```
|
|
204
243
|
|
|
205
244
|
`diffPixels` is the raw post-threshold/anti-aliasing count.
|
|
206
|
-
`
|
|
245
|
+
`diffMaskPixels` is the retained count represented by the binary mask after
|
|
207
246
|
`minClusterSize` filtering. It always matches the mask's nontransparent pixel
|
|
208
|
-
count. If `
|
|
247
|
+
count. If `diffMaskComplete` is `false`, `maxDiffs` stopped the scan early;
|
|
209
248
|
the partial mask is useful for diagnostics but not complete spatial proof.
|
|
210
249
|
Requesting `diffPixelsList` or `diffClusters` never changes that retained result.
|
|
250
|
+
`diffMaskEvidence` is returned only when `includeDiffMaskEvidence` is enabled. Its
|
|
251
|
+
native analysis hash covers every normalized option that can change retained
|
|
252
|
+
pixels, and its component pixel counts sum to `diffMaskPixels`.
|
|
211
253
|
|
|
212
254
|
The package also exports `version` from its installed manifest and
|
|
213
255
|
`maskSemanticsVersion` from the native comparison engine.
|
package/index.d.ts
CHANGED
|
@@ -60,6 +60,36 @@ export interface DiffCluster {
|
|
|
60
60
|
boundingBox: BoundingBox;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
export interface DiffMaskComponent {
|
|
64
|
+
/** Number of retained pixels in this exact 8-connected component */
|
|
65
|
+
pixelCount: number;
|
|
66
|
+
/** Bitmap-pixel bounds around the component */
|
|
67
|
+
boundingBox: BoundingBox;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface DiffMaskEvidence {
|
|
71
|
+
/** Version of this evidence result shape */
|
|
72
|
+
contractVersion: string;
|
|
73
|
+
/** Native identity of normalized options that can change retained pixels */
|
|
74
|
+
analysisContractHash: string;
|
|
75
|
+
/** Version of Honeydiff's retained-pixel semantics */
|
|
76
|
+
semanticsVersion: string;
|
|
77
|
+
/** Version of the connected-component semantics */
|
|
78
|
+
componentSemanticsVersion: string;
|
|
79
|
+
/** Bitmap coordinate-space version */
|
|
80
|
+
coordinateSpaceVersion: string;
|
|
81
|
+
/** Diff-mask width in bitmap pixels */
|
|
82
|
+
width: number;
|
|
83
|
+
/** Diff-mask height in bitmap pixels */
|
|
84
|
+
height: number;
|
|
85
|
+
/** Number of retained pixels represented by the mask */
|
|
86
|
+
pixelCount: number;
|
|
87
|
+
/** False when maxDiffs stopped the comparison early */
|
|
88
|
+
complete: boolean;
|
|
89
|
+
/** Deterministically ordered exact connected components */
|
|
90
|
+
components: DiffMaskComponent[];
|
|
91
|
+
}
|
|
92
|
+
|
|
63
93
|
export interface DiffResult {
|
|
64
94
|
/**
|
|
65
95
|
* Whether the images are different based on the comparison threshold
|
|
@@ -75,12 +105,14 @@ export interface DiffResult {
|
|
|
75
105
|
* Note: This may be > 0 even when isDifferent is false if small clusters were filtered as noise
|
|
76
106
|
*/
|
|
77
107
|
diffPixels: number;
|
|
78
|
-
/** Number of retained pixels represented by the
|
|
79
|
-
|
|
108
|
+
/** Number of retained pixels represented by the diff mask */
|
|
109
|
+
diffMaskPixels: number;
|
|
80
110
|
/** False when maxDiffs stopped the scan before the full image was evaluated */
|
|
81
|
-
|
|
82
|
-
/** Version of the pixel-retention semantics used by the
|
|
111
|
+
diffMaskComplete: boolean;
|
|
112
|
+
/** Version of the pixel-retention semantics used by the diff mask */
|
|
83
113
|
maskSemanticsVersion: string;
|
|
114
|
+
/** Authoritative diff-mask evidence (null unless includeDiffMaskEvidence is enabled) */
|
|
115
|
+
diffMaskEvidence: DiffMaskEvidence | null;
|
|
84
116
|
/** Number of pixels ignored due to anti-aliasing detection */
|
|
85
117
|
aaPixelsIgnored: number;
|
|
86
118
|
/** Percentage of pixels ignored as anti-aliasing (0.0 - 100.0) */
|
|
@@ -108,7 +140,7 @@ export interface DiffResult {
|
|
|
108
140
|
/** Installed @vizzly-testing/honeydiff package version */
|
|
109
141
|
export const version: string;
|
|
110
142
|
|
|
111
|
-
/** Native
|
|
143
|
+
/** Native diff-mask semantics implemented by this package */
|
|
112
144
|
export const maskSemanticsVersion: string;
|
|
113
145
|
|
|
114
146
|
// ============================================================================
|
|
@@ -187,6 +219,14 @@ export interface CompareOptions {
|
|
|
187
219
|
*/
|
|
188
220
|
antialiasing?: boolean;
|
|
189
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Align one conservatively detected added or removed block of rows.
|
|
224
|
+
* Falls back to the normal same-coordinate comparison when the match is
|
|
225
|
+
* ambiguous or maxDiffs is set.
|
|
226
|
+
* @default false
|
|
227
|
+
*/
|
|
228
|
+
alignHeightChanges?: boolean;
|
|
229
|
+
|
|
190
230
|
/**
|
|
191
231
|
* Maximum number of differences to detect before stopping
|
|
192
232
|
* Capped comparisons classify from observed pixel evidence because early
|
|
@@ -209,6 +249,13 @@ export interface CompareOptions {
|
|
|
209
249
|
*/
|
|
210
250
|
includeClusters?: boolean;
|
|
211
251
|
|
|
252
|
+
/**
|
|
253
|
+
* Include authoritative diff-mask dimensions, identity, and exact
|
|
254
|
+
* connected-component facts.
|
|
255
|
+
* @default false
|
|
256
|
+
*/
|
|
257
|
+
includeDiffMaskEvidence?: boolean;
|
|
258
|
+
|
|
212
259
|
/**
|
|
213
260
|
* Calculate SSIM (Structural Similarity Index) perceptual score
|
|
214
261
|
* This metric measures the source images independently of threshold and AA
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|