@vizzly-testing/honeydiff 0.0.2

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/README.md ADDED
@@ -0,0 +1,327 @@
1
+ # @vizzly-testing/honeydiff
2
+
3
+ [![npm version](https://img.shields.io/npm/v/@vizzly-testing/honeydiff.svg)](https://www.npmjs.com/package/@vizzly-testing/honeydiff)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@vizzly-testing/honeydiff.svg)](https://www.npmjs.com/package/@vizzly-testing/honeydiff)
5
+ [![CI](https://github.com/vizzly-testing/honeydiff/workflows/Node.js%20Bindings/badge.svg)](https://github.com/vizzly-testing/honeydiff/actions)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](../../LICENSE)
7
+
8
+ High-performance image diffing for Node.js - Native bindings to the Honeydiff Rust library.
9
+
10
+ Blazing fast image comparison with support for anti-aliasing detection, perceptual similarity (SSIM), spatial clustering, and variable-height screenshots. Perfect for visual regression testing.
11
+
12
+ ## Features
13
+
14
+ - **🚀 Native Performance** - Rust-powered via Neon bindings (1.1B pixels/sec for Full HD)
15
+ - **📦 Dual Input** - Works with file paths or Buffers
16
+ - **⚡ Async + Sync APIs** - Choose between non-blocking promises or synchronous operations
17
+ - **🎯 Full TypeScript Support** - Complete type definitions included
18
+ - **🔍 Advanced Analysis**:
19
+ - Anti-aliasing detection
20
+ - SSIM perceptual similarity scoring
21
+ - Spatial clustering of diff regions
22
+ - Intensity statistics (min, max, mean, median, std dev)
23
+ - Bounding box detection
24
+ - **📸 Variable Height Support** - Compare scrollable screenshots with different heights
25
+ - **🎨 Visual Artifacts** - Generate diff, mask, and overlay images
26
+ - **⚙️ Flexible Options** - Pixel tolerance, color thresholds, custom diff colors
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm install @vizzly-testing/honeydiff
32
+ ```
33
+
34
+ **Requirements:**
35
+ - Node.js 22+
36
+
37
+ **Pre-built Binaries:**
38
+ This package ships with pre-built native binaries for:
39
+ - macOS (Apple Silicon arm64)
40
+ - Linux (x64 and arm64)
41
+ - Windows (x64)
42
+
43
+ No Rust toolchain required! The correct binary is automatically loaded for your platform.
44
+
45
+ ## Quick Start
46
+
47
+ ### JavaScript (Async - Recommended)
48
+
49
+ ```javascript
50
+ const { compare, quickCompare } = require('@vizzly-testing/honeydiff');
51
+
52
+ // Quick boolean check
53
+ if (await quickCompare('baseline.png', 'current.png')) {
54
+ console.log('Visual regression detected!');
55
+ }
56
+
57
+ // Detailed comparison
58
+ const result = await compare('baseline.png', 'current.png', {
59
+ pixelTolerance: 10,
60
+ includeSSIM: true
61
+ });
62
+
63
+ console.log(`Diff: ${result.diffPercentage.toFixed(2)}%`);
64
+ console.log(`SSIM: ${result.perceptualScore}`);
65
+ ```
66
+
67
+ ### TypeScript
68
+
69
+ ```typescript
70
+ import { compare, CompareOptions, DiffResult } from '@vizzly-testing/honeydiff';
71
+
72
+ const options: CompareOptions = {
73
+ pixelTolerance: 5,
74
+ includeSSIM: true,
75
+ includeClusters: true
76
+ };
77
+
78
+ const result: DiffResult = await compare('img1.png', 'img2.png', options);
79
+
80
+ if (result.diffClusters) {
81
+ console.log(`Found ${result.diffClusters.length} diff regions`);
82
+ }
83
+ ```
84
+
85
+ ## API Reference
86
+
87
+ ### Async API (Recommended)
88
+
89
+ #### `compare(img1, img2, options?): Promise<DiffResult>`
90
+
91
+ Compare two images asynchronously. Non-blocking operation.
92
+
93
+ **Parameters:**
94
+ - `img1`: `string | Buffer` - First image (file path or Buffer)
95
+ - `img2`: `string | Buffer` - Second image (file path or Buffer)
96
+ - `options`: `CompareOptions` (optional) - Comparison configuration
97
+
98
+ **Returns:** `Promise<DiffResult>` - Detailed diff results
99
+
100
+ **Example:**
101
+ ```javascript
102
+ const result = await compare('baseline.png', 'current.png', {
103
+ pixelTolerance: 10,
104
+ antialiasing: true,
105
+ includeSSIM: true,
106
+ diffPath: '/tmp/diff.png'
107
+ });
108
+ ```
109
+
110
+ #### `quickCompare(img1, img2): Promise<boolean>`
111
+
112
+ Quick async comparison returning only a boolean.
113
+
114
+ **Returns:** `Promise<boolean>` - `true` if different, `false` if identical
115
+
116
+ ### Sync API
117
+
118
+ #### `compareSync(img1, img2, options?): DiffResult`
119
+
120
+ Synchronous comparison (blocks event loop). Use only when necessary.
121
+
122
+ #### `quickCompareSync(img1, img2): boolean`
123
+
124
+ Synchronous quick comparison returning a boolean.
125
+
126
+ ## Options
127
+
128
+ ```typescript
129
+ interface CompareOptions {
130
+ /** Pixel tolerance 0-255 (default: 0) */
131
+ pixelTolerance?: number;
132
+
133
+ /** YIQ color threshold 0.0-1.0 (default: 0.0 = RGB mode) */
134
+ colorThreshold?: number;
135
+
136
+ /** Enable anti-aliasing detection (default: true) */
137
+ antialiasing?: boolean;
138
+
139
+ /** Ignore colors, compare brightness only (default: false) */
140
+ ignoreColors?: boolean;
141
+
142
+ /** Max differences to find before stopping (default: unlimited) */
143
+ maxDiffs?: number;
144
+
145
+ /** Include detailed pixel list (default: false) */
146
+ includeDiffPixels?: boolean;
147
+
148
+ /** Include spatial clusters (default: false) */
149
+ includeClusters?: boolean;
150
+
151
+ /** Calculate SSIM score (default: false) */
152
+ includeSSIM?: boolean;
153
+
154
+ /** Path to save diff image */
155
+ diffPath?: string;
156
+
157
+ /** Path to save binary mask */
158
+ maskPath?: string;
159
+
160
+ /** Path to save side-by-side overlay */
161
+ overlayPath?: string;
162
+
163
+ /** Overwrite existing files (default: false) */
164
+ overwrite?: boolean;
165
+ }
166
+ ```
167
+
168
+ ## Result Object
169
+
170
+ ```typescript
171
+ interface DiffResult {
172
+ isDifferent: boolean;
173
+ diffPercentage: number;
174
+ totalPixels: number;
175
+ diffPixels: number;
176
+ aaPixelsIgnored: number;
177
+ aaPercentage: number;
178
+ boundingBox: BoundingBox | null;
179
+ heightDiff: HeightDiff | null;
180
+ diffPixelsList: DiffPixel[] | null;
181
+ diffClusters: DiffCluster[] | null;
182
+ intensityStats: IntensityStats | null;
183
+ perceptualScore: number | null; // SSIM 0.0-1.0
184
+ }
185
+ ```
186
+
187
+ ## Usage Examples
188
+
189
+ ### With Buffers
190
+
191
+ ```javascript
192
+ const fs = require('fs');
193
+ const { compare } = require('@vizzly-testing/honeydiff');
194
+
195
+ const img1 = fs.readFileSync('image1.png');
196
+ const img2 = fs.readFileSync('image2.png');
197
+
198
+ const result = await compare(img1, img2, {
199
+ pixelTolerance: 5
200
+ });
201
+ ```
202
+
203
+ ### Generate Diff Images
204
+
205
+ ```javascript
206
+ const result = await compare('baseline.png', 'current.png', {
207
+ diffPath: './output/diff.png',
208
+ maskPath: './output/mask.png',
209
+ overlayPath: './output/overlay.png',
210
+ overwrite: true
211
+ });
212
+
213
+ console.log(`Diff images saved with ${result.diffPercentage}% difference`);
214
+ ```
215
+
216
+ ### Spatial Clustering
217
+
218
+ ```javascript
219
+ const result = await compare('img1.png', 'img2.png', {
220
+ includeClusters: true
221
+ });
222
+
223
+ if (result.diffClusters) {
224
+ result.diffClusters.forEach((cluster, i) => {
225
+ console.log(`Cluster ${i + 1}:`);
226
+ console.log(` Pixels: ${cluster.pixelCount}`);
227
+ console.log(` Center: (${cluster.centerOfMass[0]}, ${cluster.centerOfMass[1]})`);
228
+ console.log(` Bounds: ${cluster.boundingBox.width}x${cluster.boundingBox.height}`);
229
+ });
230
+ }
231
+ ```
232
+
233
+ ### Perceptual Similarity (SSIM)
234
+
235
+ ```javascript
236
+ const result = await compare('img1.png', 'img2.png', {
237
+ includeSSIM: true
238
+ });
239
+
240
+ if (result.perceptualScore !== null) {
241
+ if (result.perceptualScore > 0.95) {
242
+ console.log('Perceptually very similar');
243
+ } else if (result.perceptualScore > 0.80) {
244
+ console.log('Somewhat similar');
245
+ } else {
246
+ console.log('Perceptually different');
247
+ }
248
+ }
249
+ ```
250
+
251
+ ### Intensity Statistics
252
+
253
+ ```javascript
254
+ const result = await compare('img1.png', 'img2.png', {
255
+ includeDiffPixels: true // Enables intensity stats
256
+ });
257
+
258
+ if (result.intensityStats) {
259
+ console.log(`Intensity range: ${result.intensityStats.min}-${result.intensityStats.max}`);
260
+ console.log(`Mean: ${result.intensityStats.mean.toFixed(1)}`);
261
+ console.log(`Median: ${result.intensityStats.median}`);
262
+ console.log(`Std Dev: ${result.intensityStats.stdDev.toFixed(1)}`);
263
+ }
264
+ ```
265
+
266
+ ## Performance
267
+
268
+ Benchmarks on M-series Mac:
269
+
270
+ | Image Size | Time | Throughput |
271
+ |------------|------|------------|
272
+ | 1920x1080 (Full HD) | ~2ms | 1.1B pixels/sec |
273
+ | 3840x2160 (4K) | ~3ms | 3.0B pixels/sec |
274
+
275
+ With diff artifact generation: ~30-35ms for Full HD images
276
+
277
+ ## Variable Height Support
278
+
279
+ Honeydiff can compare images with different heights (same width) - perfect for scrollable screenshots:
280
+
281
+ ```javascript
282
+ const result = await compare('short.png', 'tall.png');
283
+
284
+ if (result.heightDiff) {
285
+ console.log(`Height diff: ${result.heightDiff.height1}px vs ${result.heightDiff.height2}px`);
286
+ console.log(`Extra pixels: ${result.heightDiff.extraPixels}`);
287
+ }
288
+ ```
289
+
290
+ ## Building from Source
291
+
292
+ Only needed if you want to contribute or modify the native code.
293
+
294
+ **Prerequisites:**
295
+ - Rust toolchain (install from https://rustup.rs)
296
+ - Node.js 22+
297
+
298
+ ```bash
299
+ # Clone the repository
300
+ git clone https://github.com/vizzly-testing/honeydiff
301
+ cd honeydiff/crates/honeydiff-node
302
+
303
+ # Install dependencies
304
+ npm install
305
+
306
+ # Build for your platform
307
+ npm run build
308
+
309
+ # Run examples
310
+ node examples/basic.js
311
+ ```
312
+
313
+ ### Cross-Platform Builds
314
+
315
+ ```bash
316
+ # Build for all supported platforms (requires cross-compilation setup)
317
+ npm run cross-build
318
+ ```
319
+
320
+ ## Related Projects
321
+
322
+ - [honeydiff](https://github.com/vizzly-testing/honeydiff) - The core Rust library
323
+ - [Vizzly](https://github.com/vizzly-testing/vizzly) - Visual regression testing platform
324
+
325
+ ## License
326
+
327
+ MIT - See [LICENSE](../../LICENSE) for details
package/index.d.ts ADDED
@@ -0,0 +1,276 @@
1
+ /**
2
+ * TypeScript definitions for @vizzly-testing/honeydiff
3
+ * High-performance image diffing for Node.js
4
+ */
5
+
6
+ // ============================================================================
7
+ // Core Types
8
+ // ============================================================================
9
+
10
+ export interface BoundingBox {
11
+ /** X coordinate of top-left corner */
12
+ x: number;
13
+ /** Y coordinate of top-left corner */
14
+ y: number;
15
+ /** Width of the bounding box */
16
+ width: number;
17
+ /** Height of the bounding box */
18
+ height: number;
19
+ }
20
+
21
+ export interface HeightDiff {
22
+ /** Height of the first image in pixels */
23
+ height1: number;
24
+ /** Height of the second image in pixels */
25
+ height2: number;
26
+ /** Number of extra pixels due to height difference */
27
+ extraPixels: number;
28
+ }
29
+
30
+ export interface DiffPixel {
31
+ /** X coordinate of the differing pixel */
32
+ x: number;
33
+ /** Y coordinate of the differing pixel */
34
+ y: number;
35
+ /** Intensity of the difference (0-255, higher = more different) */
36
+ intensity: number;
37
+ }
38
+
39
+ export interface IntensityStats {
40
+ /** Maximum difference intensity observed (0-255) */
41
+ max: number;
42
+ /** Minimum difference intensity observed (0-255) */
43
+ min: number;
44
+ /** Mean (average) difference intensity */
45
+ mean: number;
46
+ /** Median difference intensity */
47
+ median: number;
48
+ /** Standard deviation of difference intensities */
49
+ stdDev: number;
50
+ }
51
+
52
+ export interface DiffCluster {
53
+ /** Number of pixels in this cluster */
54
+ pixelCount: number;
55
+ /** Center of mass [x, y] coordinates */
56
+ centerOfMass: [number, number];
57
+ /** Average intensity of differences in this cluster */
58
+ avgIntensity: number;
59
+ /** Bounding box containing this cluster */
60
+ boundingBox: BoundingBox;
61
+ }
62
+
63
+ export interface DiffResult {
64
+ /** Whether the images are different based on the comparison threshold */
65
+ isDifferent: boolean;
66
+ /** Percentage of pixels that differ (0.0 - 100.0) */
67
+ diffPercentage: number;
68
+ /** Total number of pixels compared */
69
+ totalPixels: number;
70
+ /** Number of pixels that differ */
71
+ diffPixels: number;
72
+ /** Number of pixels ignored due to anti-aliasing detection */
73
+ aaPixelsIgnored: number;
74
+ /** Percentage of pixels ignored as anti-aliasing (0.0 - 100.0) */
75
+ aaPercentage: number;
76
+ /** Bounding box containing all differences (null if identical) */
77
+ boundingBox: BoundingBox | null;
78
+ /** Height difference information (null if same height) */
79
+ heightDiff: HeightDiff | null;
80
+ /** List of differing pixels with positions and intensities (null unless includeDiffPixels is enabled) */
81
+ diffPixelsList: DiffPixel[] | null;
82
+ /** Clustered groups of connected differing pixels (null unless includeClusters is enabled) */
83
+ diffClusters: DiffCluster[] | null;
84
+ /** Statistical metrics about difference intensities (null unless includeDiffPixels is enabled) */
85
+ intensityStats: IntensityStats | null;
86
+ /** SSIM (Structural Similarity Index) perceptual score 0.0-1.0 (null unless includeSSIM is enabled) */
87
+ perceptualScore: number | null;
88
+ }
89
+
90
+ // ============================================================================
91
+ // Options
92
+ // ============================================================================
93
+
94
+ export interface CompareOptions {
95
+ /**
96
+ * Pixel difference threshold (0-255). Differences below this are ignored.
97
+ * NOTE: When using YIQ comparison, use colorThreshold instead (0.0-1.0)
98
+ * @default 0
99
+ */
100
+ pixelTolerance?: number;
101
+
102
+ /**
103
+ * Color difference threshold for YIQ comparison (0.0-1.0)
104
+ * Set to 0.0 to use RGB comparison (default)
105
+ * Set to 0.1 for odiff-style YIQ comparison
106
+ * @default 0.0
107
+ */
108
+ colorThreshold?: number;
109
+
110
+ /**
111
+ * Enable anti-aliasing detection to ignore AA differences
112
+ * @default true
113
+ */
114
+ antialiasing?: boolean;
115
+
116
+ /**
117
+ * Ignore color differences (compare only structure/brightness)
118
+ * @default false
119
+ */
120
+ ignoreColors?: boolean;
121
+
122
+ /**
123
+ * Maximum number of differences to detect before stopping
124
+ * @default undefined (unlimited)
125
+ */
126
+ maxDiffs?: number;
127
+
128
+ /**
129
+ * Include list of differing pixels with positions and intensities
130
+ * WARNING: This can use significant memory for images with many differences
131
+ * @default false
132
+ */
133
+ includeDiffPixels?: boolean;
134
+
135
+ /**
136
+ * Include clustered groups of connected differing pixels
137
+ * Automatically enables includeDiffPixels if not already enabled
138
+ * Clusters are sorted by size (largest first)
139
+ * @default false
140
+ */
141
+ includeClusters?: boolean;
142
+
143
+ /**
144
+ * Calculate SSIM (Structural Similarity Index) perceptual score
145
+ * WARNING: SSIM can be computationally expensive on large images
146
+ * @default false
147
+ */
148
+ includeSSIM?: boolean;
149
+
150
+ /**
151
+ * Path to save the diff image (highlighted differences)
152
+ * @default undefined
153
+ */
154
+ diffPath?: string;
155
+
156
+ /**
157
+ * Path to save the mask image (binary diff mask)
158
+ * @default undefined
159
+ */
160
+ maskPath?: string;
161
+
162
+ /**
163
+ * Path to save the overlay image (side-by-side comparison)
164
+ * @default undefined
165
+ */
166
+ overlayPath?: string;
167
+
168
+ /**
169
+ * Whether to overwrite existing output files
170
+ * @default false
171
+ */
172
+ overwrite?: boolean;
173
+ }
174
+
175
+ // ============================================================================
176
+ // Input Types
177
+ // ============================================================================
178
+
179
+ /** Image input can be a file path or a Buffer containing image data */
180
+ export type ImageInput = string | Buffer;
181
+
182
+ // ============================================================================
183
+ // API Functions
184
+ // ============================================================================
185
+
186
+ /**
187
+ * Compare two images asynchronously (recommended)
188
+ *
189
+ * @param img1 - First image (file path or Buffer)
190
+ * @param img2 - Second image (file path or Buffer)
191
+ * @param options - Comparison options
192
+ * @returns Promise resolving to detailed diff results
193
+ *
194
+ * @example
195
+ * ```typescript
196
+ * const result = await compare('baseline.png', 'current.png', {
197
+ * pixelTolerance: 10,
198
+ * includeSSIM: true
199
+ * });
200
+ *
201
+ * console.log(`Diff: ${result.diffPercentage.toFixed(2)}%`);
202
+ * console.log(`SSIM: ${result.perceptualScore}`);
203
+ * ```
204
+ */
205
+ export function compare(
206
+ img1: ImageInput,
207
+ img2: ImageInput,
208
+ options?: CompareOptions
209
+ ): Promise<DiffResult>;
210
+
211
+ /**
212
+ * Quick asynchronous comparison (returns only boolean)
213
+ *
214
+ * @param img1 - First image (file path or Buffer)
215
+ * @param img2 - Second image (file path or Buffer)
216
+ * @returns Promise resolving to true if different, false if identical
217
+ *
218
+ * @example
219
+ * ```typescript
220
+ * if (await quickCompare('baseline.png', 'current.png')) {
221
+ * console.log('Visual regression detected!');
222
+ * }
223
+ * ```
224
+ */
225
+ export function quickCompare(
226
+ img1: ImageInput,
227
+ img2: ImageInput
228
+ ): Promise<boolean>;
229
+
230
+ /**
231
+ * Compare two images synchronously (blocks event loop)
232
+ *
233
+ * Use this only when you need blocking behavior.
234
+ * For most cases, prefer the async compare() function.
235
+ *
236
+ * @param img1 - First image (file path or Buffer)
237
+ * @param img2 - Second image (file path or Buffer)
238
+ * @param options - Comparison options
239
+ * @returns Detailed diff results
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const result = compareSync('baseline.png', 'current.png', {
244
+ * pixelTolerance: 5,
245
+ * includeClusters: true
246
+ * });
247
+ *
248
+ * if (result.diffClusters) {
249
+ * console.log(`Found ${result.diffClusters.length} diff regions`);
250
+ * }
251
+ * ```
252
+ */
253
+ export function compareSync(
254
+ img1: ImageInput,
255
+ img2: ImageInput,
256
+ options?: CompareOptions
257
+ ): DiffResult;
258
+
259
+ /**
260
+ * Quick synchronous comparison (returns only boolean, blocks event loop)
261
+ *
262
+ * @param img1 - First image (file path or Buffer)
263
+ * @param img2 - Second image (file path or Buffer)
264
+ * @returns true if different, false if identical
265
+ *
266
+ * @example
267
+ * ```typescript
268
+ * if (quickCompareSync('baseline.png', 'current.png')) {
269
+ * console.log('Images differ');
270
+ * }
271
+ * ```
272
+ */
273
+ export function quickCompareSync(
274
+ img1: ImageInput,
275
+ img2: ImageInput
276
+ ): boolean;
package/index.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * @vizzly-testing/honeydiff - Native Node.js bindings for Honeydiff
3
+ */
4
+
5
+ let addon;
6
+
7
+ try {
8
+ // Load the platform-specific native addon
9
+ addon = require('./load-platform.js');
10
+ } catch (e) {
11
+ throw new Error(
12
+ '@vizzly-testing/honeydiff failed to load native binary.\n' +
13
+ 'Platform: ' + process.platform + ' ' + process.arch + '\n' +
14
+ 'Original error: ' + e.message
15
+ );
16
+ }
17
+
18
+ // Export all functions from the native addon
19
+ module.exports = {
20
+ compare: addon.compare,
21
+ quickCompare: addon.quickCompare,
22
+ compareSync: addon.compareSync,
23
+ quickCompareSync: addon.quickCompareSync,
24
+ };
@@ -0,0 +1,25 @@
1
+ const os = require('os');
2
+ const path = require('path');
3
+
4
+ function getPlatformBinary() {
5
+ const platform = os.platform();
6
+ const arch = os.arch();
7
+
8
+ let target;
9
+ if (platform === 'darwin' && arch === 'arm64') {
10
+ target = 'aarch64-apple-darwin';
11
+ } else if (platform === 'linux' && arch === 'x64') {
12
+ target = 'x86_64-unknown-linux-gnu';
13
+ } else if (platform === 'linux' && arch === 'arm64') {
14
+ target = 'aarch64-unknown-linux-gnu';
15
+ } else if (platform === 'win32' && arch === 'x64') {
16
+ target = 'x86_64-pc-windows-msvc';
17
+ } else {
18
+ throw new Error(`Unsupported platform: ${platform} ${arch}. Supported: macOS ARM64, Linux x64/ARM64, Windows x64`);
19
+ }
20
+
21
+ const binaryPath = path.join(__dirname, 'platforms', `index-${target}.node`);
22
+ return require(binaryPath);
23
+ }
24
+
25
+ module.exports = getPlatformBinary();
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@vizzly-testing/honeydiff",
3
+ "version": "0.0.2",
4
+ "description": "High-performance image diffing for Node.js - Native bindings to Honeydiff Rust library",
5
+ "main": "index.js",
6
+ "types": "index.d.ts",
7
+ "neon": {
8
+ "targets": [
9
+ "x86_64-pc-windows-msvc",
10
+ "aarch64-apple-darwin",
11
+ "x86_64-unknown-linux-gnu",
12
+ "aarch64-unknown-linux-gnu"
13
+ ]
14
+ },
15
+ "scripts": {
16
+ "build": "cargo build --release",
17
+ "build-debug": "cargo build",
18
+ "test": "node examples/basic.js",
19
+ "clean": "cargo clean && rm -f index.node"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/vizzly-testing/honeydiff.git",
24
+ "directory": "crates/honeydiff-node"
25
+ },
26
+ "keywords": [
27
+ "image",
28
+ "diff",
29
+ "comparison",
30
+ "visual-regression",
31
+ "testing",
32
+ "screenshot",
33
+ "rust",
34
+ "neon",
35
+ "native"
36
+ ],
37
+ "author": "Robert DeLuca",
38
+ "license": "MIT",
39
+ "files": [
40
+ "index.js",
41
+ "index.d.ts",
42
+ "index.node",
43
+ "README.md",
44
+ "index.js",
45
+ "index.d.ts",
46
+ "load-platform.js",
47
+ "platforms/*.node",
48
+ "README.md"
49
+ ],
50
+ "engines": {
51
+ "node": ">=22.0.0"
52
+ }
53
+ }