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 +6 -0
- package/README.md +2 -2
- package/bin/image-guard.test.js +12 -2
- package/package.json +1 -1
- package/src/utils.js +6 -6
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
|
|
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
|
|
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
|
|
package/bin/image-guard.test.js
CHANGED
|
@@ -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
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
|
|
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))
|