metalsmith-optimize-images 0.9.3 → 0.10.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/README.md +12 -49
- package/lib/index.cjs +13 -27
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +13 -27
- package/lib/index.js.map +1 -1
- package/package.json +3 -1
package/README.md
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
# metalsmith-optimize-images
|
|
2
2
|
|
|
3
|
-
> **🚀 Release Candidate**: This plugin has achieved comprehensive test coverage (95.27%) and is ready for production testing. Recent critical bug fixes have resolved recursive processing and AVIF format issues. Feedback welcome before 1.0.0 release!
|
|
4
|
-
|
|
5
3
|
Metalsmith plugin for generating responsive images with optimal formats
|
|
6
4
|
|
|
7
5
|
[![metalsmith:plugin][metalsmith-badge]][metalsmith-url]
|
|
@@ -11,16 +9,18 @@ Metalsmith plugin for generating responsive images with optimal formats
|
|
|
11
9
|
[![ESM/CommonJS][modules-badge]][npm-url]
|
|
12
10
|
[](https://snyk.io/test/npm/metalsmith-optimize-images)
|
|
13
11
|
|
|
12
|
+
> This Metalsmith plugin is under active development. The API is stable, but breaking changes may occur before reaching 1.0.0.
|
|
13
|
+
|
|
14
14
|
## Features
|
|
15
15
|
|
|
16
16
|
- **Multiple image formats**: Generates AVIF and WebP variants with JPEG/PNG fallbacks
|
|
17
17
|
- **Responsive sizes**: Creates different image sizes for various device widths
|
|
18
18
|
- **Background image support**: Automatically processes unused images for CSS `image-set()` backgrounds
|
|
19
19
|
- **Progressive loading**: Optional progressive image loading with low-quality placeholders
|
|
20
|
-
- **Lazy loading**: Uses native browser lazy loading
|
|
20
|
+
- **Lazy loading**: Uses native browser lazy loading
|
|
21
21
|
- **Content-based hashing**: Adds hash to filenames for optimal caching
|
|
22
22
|
- **Layout shift prevention**: Adds width/height attributes
|
|
23
|
-
- **Parallel processing**: Processes images in parallel
|
|
23
|
+
- **Parallel processing**: Processes images in parallel
|
|
24
24
|
- **Metadata generation**: Creates a JSON manifest with image information and variants
|
|
25
25
|
- **Configurable compression**: Customize compression settings per format
|
|
26
26
|
- **ESM and CommonJS support**:
|
|
@@ -33,20 +33,6 @@ Metalsmith plugin for generating responsive images with optimal formats
|
|
|
33
33
|
npm install metalsmith-optimize-images
|
|
34
34
|
```
|
|
35
35
|
|
|
36
|
-
## Requirements
|
|
37
|
-
|
|
38
|
-
- Node.js >=18.0.0
|
|
39
|
-
- Metalsmith >=2.5.0
|
|
40
|
-
|
|
41
|
-
## Platform Testing Status
|
|
42
|
-
|
|
43
|
-
- ✅ **macOS**: Fully tested and working
|
|
44
|
-
- 🔄 **Windows**: Seeking community feedback on Sharp.js compatibility
|
|
45
|
-
- 🔄 **Linux**: Seeking validation across different distributions
|
|
46
|
-
- 🔄 **CI/CD**: Testing in various containerized environments
|
|
47
|
-
|
|
48
|
-
**Help us reach 1.0.0**: If you test this plugin on Windows, Linux, or in production environments, please [share your experience](https://github.com/wernerglinka/metalsmith-optimize-images/issues)!
|
|
49
|
-
|
|
50
36
|
## Usage
|
|
51
37
|
|
|
52
38
|
> This plugin **must** be run after assets are copied but before any final HTML processing.
|
|
@@ -228,7 +214,6 @@ After processing HTML-referenced images, the plugin:
|
|
|
228
214
|
- **1x variant**: Half the original size for regular displays
|
|
229
215
|
- **2x variant**: Original image size for retina displays (sharper on high-DPI screens)
|
|
230
216
|
5. **Creates all formats** (AVIF, WebP, original) for optimal browser support
|
|
231
|
-
6. **No HTML replacement** - you manually write CSS with `image-set()`
|
|
232
217
|
|
|
233
218
|
### Using Background Images with CSS
|
|
234
219
|
|
|
@@ -284,10 +269,8 @@ metalsmith.use(
|
|
|
284
269
|
|
|
285
270
|
- **Automatic format optimization** - Browser selects best supported format
|
|
286
271
|
- **Retina display support** - 2x variants provide crisp images on high-DPI screens
|
|
287
|
-
- **Smart sizing** - Uses actual image dimensions instead of arbitrary widths
|
|
288
272
|
- **No manual work** - Plugin automatically finds and processes unused images in Metalsmith files object
|
|
289
273
|
- **Consistent workflow** - Same formats and quality settings as HTML images
|
|
290
|
-
- **Efficient processing** - Parallel processing of sizes and formats
|
|
291
274
|
|
|
292
275
|
## Progressive Loading
|
|
293
276
|
|
|
@@ -439,39 +422,19 @@ metalsmith.env('DEBUG', 'metalsmith-optimize-images*');
|
|
|
439
422
|
}
|
|
440
423
|
```
|
|
441
424
|
|
|
442
|
-
##
|
|
443
|
-
|
|
444
|
-
### Bug Fixes (January 2025)
|
|
445
|
-
|
|
446
|
-
- **🚫 Fixed Recursive Processing**: Resolved critical issue where the background image processor was finding already-generated responsive images and reprocessing them recursively, creating malformed filenames like `image-320w-640w-960w.jpg`
|
|
447
|
-
- **🚫 Fixed HEIF Extension Issue**: Fixed Sharp.js AVIF processing that was sometimes generating `.heif` extensions instead of `.avif`
|
|
448
|
-
- **✅ Enhanced Background Image Filtering**: Added comprehensive filtering to prevent responsive variants from being treated as source images
|
|
449
|
-
|
|
450
|
-
## Feedback & Testing
|
|
451
|
-
|
|
452
|
-
This plugin is approaching 1.0.0 and we'd love your feedback! Please test and report:
|
|
453
|
-
|
|
454
|
-
### Especially Needed
|
|
455
|
-
|
|
456
|
-
- **Windows compatibility**: Sharp.js native compilation and image processing
|
|
457
|
-
- **Large image batches**: Performance with 50+ images
|
|
458
|
-
- **Memory usage**: Resource consumption in your environment
|
|
459
|
-
- **Cross-platform consistency**: Image quality and file sizes across platforms
|
|
460
|
-
- **Progressive loading**: Behavior across different browsers
|
|
461
|
-
- **Background image processing**: Testing the new `image-set()` feature with CSS backgrounds
|
|
425
|
+
## License
|
|
462
426
|
|
|
463
|
-
|
|
427
|
+
MIT
|
|
464
428
|
|
|
465
|
-
|
|
466
|
-
- ✅ Real Metalsmith integration tests (no mocks)
|
|
467
|
-
- ✅ Tested on macOS with Node.js 18+
|
|
468
|
-
- 🔄 Seeking broader platform validation
|
|
429
|
+
## Development transparency
|
|
469
430
|
|
|
470
|
-
|
|
431
|
+
Portions of this project were developed with the assistance of AI tools including Claude and Claude Code. These tools were used to:
|
|
471
432
|
|
|
472
|
-
|
|
433
|
+
- Generate or refactor code
|
|
434
|
+
- Assist with documentation
|
|
435
|
+
- Troubleshoot bugs and explore alternative approaches
|
|
473
436
|
|
|
474
|
-
|
|
437
|
+
All AI-assisted code has been reviewed and tested to ensure it meets project standards. See the included [CLAUDE.md](CLAUDE.md) file for more details.
|
|
475
438
|
|
|
476
439
|
[npm-badge]: https://img.shields.io/npm/v/metalsmith-optimize-images.svg
|
|
477
440
|
[npm-url]: https://www.npmjs.com/package/metalsmith-optimize-images
|
package/lib/index.cjs
CHANGED
|
@@ -889,6 +889,12 @@ function replacePictureElement($, $img, variants, config) {
|
|
|
889
889
|
*/
|
|
890
890
|
async function processHtmlFile(htmlFile, fileData, files, metalsmith, processedImages, debug, config) {
|
|
891
891
|
debug(`Processing HTML file: ${htmlFile}`);
|
|
892
|
+
|
|
893
|
+
// Validate file.contents before processing
|
|
894
|
+
if (!fileData.contents || !Buffer.isBuffer(fileData.contents)) {
|
|
895
|
+
debug(`Skipping ${htmlFile}: invalid or missing file contents`);
|
|
896
|
+
return;
|
|
897
|
+
}
|
|
892
898
|
const content = fileData.contents.toString();
|
|
893
899
|
|
|
894
900
|
// Parse HTML
|
|
@@ -1118,33 +1124,8 @@ function injectProgressiveAssets($) {
|
|
|
1118
1124
|
* Creates a responsive images plugin for Metalsmith
|
|
1119
1125
|
* Generates multiple sizes and formats of images and replaces img tags with picture elements
|
|
1120
1126
|
*
|
|
1121
|
-
* @param {
|
|
1122
|
-
* @
|
|
1123
|
-
* @param {string[]} [options.formats] - Array of image formats to generate (in order of preference)
|
|
1124
|
-
* @param {Object} [options.formatOptions] - Format-specific compression settings
|
|
1125
|
-
* @param {Object} [options.formatOptions.avif] - AVIF compression options
|
|
1126
|
-
* @param {Object} [options.formatOptions.webp] - WebP compression options
|
|
1127
|
-
* @param {Object} [options.formatOptions.jpeg] - JPEG compression options
|
|
1128
|
-
* @param {Object} [options.formatOptions.png] - PNG compression options
|
|
1129
|
-
* @param {string} [options.htmlPattern] - Glob pattern to match HTML files
|
|
1130
|
-
* @param {string} [options.imgSelector] - CSS selector for images to process
|
|
1131
|
-
* @param {string} [options.outputDir] - Output directory for processed images
|
|
1132
|
-
* @param {string} [options.outputPattern] - Output naming pattern
|
|
1133
|
-
* @param {boolean} [options.skipLarger] - Whether to skip generating sizes larger than original
|
|
1134
|
-
* @param {boolean} [options.lazy] - Whether to add loading="lazy" to images
|
|
1135
|
-
* @param {boolean} [options.dimensionAttributes] - Whether to add width/height attributes
|
|
1136
|
-
* @param {string} [options.sizes] - Default sizes attribute
|
|
1137
|
-
* @param {number} [options.concurrency] - Maximum number of images to process in parallel
|
|
1138
|
-
* @param {boolean} [options.generateMetadata] - Whether to generate a metadata JSON file
|
|
1139
|
-
* @param {boolean} [options.isProgressive] - Whether to use progressive image loading (default: true)
|
|
1140
|
-
* @param {Object} [options.placeholder] - Placeholder image settings for progressive loading
|
|
1141
|
-
* @param {number} [options.placeholder.width] - Placeholder image width (default: 50)
|
|
1142
|
-
* @param {number} [options.placeholder.quality] - Placeholder image quality (default: 30)
|
|
1143
|
-
* @param {number} [options.placeholder.blur] - Placeholder image blur amount (default: 10)
|
|
1144
|
-
* @param {boolean} [options.processUnusedImages] - Whether to process unused images for background use (default: true)
|
|
1145
|
-
* @param {string} [options.imagePattern] - Glob pattern to find images for background processing (default: `**\/*.{jpg,jpeg,png,gif,webp,avif}`)
|
|
1146
|
-
* @param {string} [options.imageFolder] - Folder to scan for background images, relative to source (default: 'lib/assets/images')
|
|
1147
|
-
* @return {Function} - Metalsmith plugin function
|
|
1127
|
+
* @param {Options} [options={}] - Configuration options for the plugin
|
|
1128
|
+
* @returns {import('metalsmith').Plugin} - Metalsmith plugin function
|
|
1148
1129
|
*/
|
|
1149
1130
|
function optimizeImagesPlugin(options = {}) {
|
|
1150
1131
|
// Build configuration with defaults and user options
|
|
@@ -1570,5 +1551,10 @@ function generateBackgroundVariantPath(originalPath, width, format, config) {
|
|
|
1570
1551
|
return path__default["default"].join(config.outputDir, outputName);
|
|
1571
1552
|
}
|
|
1572
1553
|
|
|
1554
|
+
// Set function name for better debugging
|
|
1555
|
+
Object.defineProperty(optimizeImagesPlugin, 'name', {
|
|
1556
|
+
value: 'metalsmith-optimize-images'
|
|
1557
|
+
});
|
|
1558
|
+
|
|
1573
1559
|
module.exports = optimizeImagesPlugin;
|
|
1574
1560
|
//# sourceMappingURL=index.cjs.map
|