image-guard 5.2.1 → 5.2.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/CHANGELOG.md CHANGED
@@ -4,6 +4,12 @@ Starting with version 5.2.0, all notable changes to Image Guard are documented i
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and the project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
+ ## [5.2.2] - 2026-02-17
8
+
9
+ ### Fixed
10
+
11
+ * Updated HEIC dry run to report actual file sizes instead of omitting size data
12
+
7
13
  ## [5.2.1] - 2026-02-17
8
14
 
9
15
  ### Changed
package/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  (This project was based on [sum.cumo’s imagemin-merlin](https://github.com/sumcumo/imagemin-merlin). [Changes are documented](https://github.com/sumcumo/imagemin-merlin/compare/master...j9t:master), and include this README. Image Guard supports additional file formats—WebP, AVIF, and HEIC/HEIF—, comes with improved code and documentation, and is being maintained. For this reason, it’s [not based on any Imagemin packages](https://meiert.com/blog/image-guard-4/) anymore.)
6
6
 
7
- Image Guard takes care of near-lossless compression of your images, to help you avoid bloat in your repositories. It makes it convenient and as safe as possible to automatically compress PNG, JPG, GIF, WebP, and AVIF images. It can also convert HEIC/HEIF files to AVIF (opt-in via `--heic-to-avif`).
7
+ Image Guard takes care of near-lossless compression of your images, to help you avoid bloat in your repositories. It makes it convenient and as safe as possible to automatically compress PNG, JPG, GIF, WebP, and AVIF images. It can also convert HEIC/HEIF files to AVIF.
8
8
 
9
9
  It’s convenient because setup is simple. Run it right away—done. Or install, run, add hook—done.
10
10
 
@@ -140,7 +140,7 @@ Roughly like this:
140
140
  * Green: The image file has been compressed.
141
141
  * Cyan: The image file has been converted (HEIC/HEIF to AVIF).
142
142
  * White (light gray): The image file has not been changed.
143
- * Blue: The image file had already been compressed more aggressively than the new result, and was therefore skipped, too.
143
+ * Blue: The image file had already been compressed more effectively than the new result, and was therefore skipped, too.
144
144
 
145
145
  Tip: Use `--quiet` to suppress these per‑file lines and keep only the final summary.
146
146
 
@@ -451,19 +451,26 @@ describe('Image Guard', () => {
451
451
  fs.rmSync(tempDir, { recursive: true, force: true })
452
452
  })
453
453
 
454
- test('Dry run does not convert HEIC files', () => {
454
+ test('Dry run does not convert HEIC files but reports sizes', () => {
455
455
  const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'image-guard-heic-dry-'))
456
456
  const tempTestFolder = path.join(tempDir, 'test')
457
457
  copyFiles(testFolder, tempTestFolder)
458
458
 
459
+ // Remove pre-existing AVIF so the conversion path is exercised
460
+ const avifFile = path.join(tempTestFolder, 'test.avif')
461
+ if (fs.existsSync(avifFile)) {
462
+ fs.unlinkSync(avifFile)
463
+ }
464
+
459
465
  const heicFile = path.join(tempTestFolder, 'test.heic')
460
466
  const heicBefore = fs.statSync(heicFile)
461
467
  const filesBefore = fs.readdirSync(tempTestFolder).sort()
462
468
 
463
469
  const originalCwd = process.cwd()
470
+ let output = ''
464
471
  try {
465
472
  process.chdir(tempDir)
466
- execSync(`node "${imageGuardScript}" --heic-to-avif --dry`, { stdio: 'pipe' })
473
+ output = execSync(`node "${imageGuardScript}" --heic-to-avif --dry`, { encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'] })
467
474
  } finally {
468
475
  process.chdir(originalCwd)
469
476
  }
@@ -477,6 +484,9 @@ describe('Image Guard', () => {
477
484
  const filesAfter = fs.readdirSync(tempTestFolder).sort()
478
485
  assert.deepStrictEqual(filesAfter, filesBefore)
479
486
 
487
+ // Dry run should report size data for HEIC conversion
488
+ assert.match(output, /Converted.*test\.heic.*KB.*→.*KB/i, 'Dry run should report HEIC conversion sizes')
489
+
480
490
  fs.rmSync(tempDir, { recursive: true, force: true })
481
491
  })
482
492
 
package/package.json CHANGED
@@ -46,5 +46,5 @@
46
46
  "test": "node --test bin/image-guard.test.js"
47
47
  },
48
48
  "type": "module",
49
- "version": "5.2.1"
49
+ "version": "5.2.2"
50
50
  }
package/src/utils.js CHANGED
@@ -133,7 +133,7 @@ const compression = async (filename, dry, quiet = false) => {
133
133
  } else if (fileSizeAfter > fileSizeBefore) {
134
134
  color = 'blue'
135
135
  status = 'Skipped'
136
- details = 'already compressed more aggressively'
136
+ details = 'already compressed more effectively'
137
137
  }
138
138
 
139
139
  logMessage(`${status} ${filename} (${details})`, dry, color, quiet)
@@ -227,11 +227,6 @@ const conversion = async (filename, dry, keepOriginal, quiet = false) => {
227
227
  const inputBuffer = await fs.promises.readFile(filename)
228
228
  const { width, height, data } = await decode({ buffer: inputBuffer })
229
229
 
230
- if (dry) {
231
- logMessage(`Converted ${filename} → ${path.basename(avifPath)}`, dry, 'cyan', quiet)
232
- return 0
233
- }
234
-
235
230
  // Encode as lossy AVIF—HEIC sources are already lossy (HEVC), so lossless
236
231
  // re-encoding would inflate file sizes without any quality benefit
237
232
  await sharp(data, { raw: { width, height, channels: 4 } })
@@ -242,6 +237,11 @@ const conversion = async (filename, dry, keepOriginal, quiet = false) => {
242
237
 
243
238
  logMessage(`Converted ${filename} → ${path.basename(avifPath)} (${sizeReadable(fileSizeBefore)} → ${sizeReadable(fileSizeAfter)})`, dry, 'cyan', quiet)
244
239
 
240
+ if (dry) {
241
+ await retryFileOperation(() => fs.promises.unlink(avifPath))
242
+ return 0
243
+ }
244
+
245
245
  // Delete original HEIC/HEIF file unless `--keep-heic` is set
246
246
  if (!keepOriginal) {
247
247
  await retryFileOperation(() => fs.promises.unlink(filename))