metalsmith-optimize-images 0.1.1 → 0.9.3
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 +333 -68
- package/lib/index.cjs +1034 -72
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +1032 -70
- package/lib/index.js.map +1 -1
- package/package.json +10 -11
package/README.md
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
# metalsmith-optimize-images
|
|
2
2
|
|
|
3
|
-
>
|
|
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
4
|
|
|
5
5
|
Metalsmith plugin for generating responsive images with optimal formats
|
|
6
6
|
|
|
7
7
|
[![metalsmith:plugin][metalsmith-badge]][metalsmith-url]
|
|
8
8
|
[![npm: version][npm-badge]][npm-url]
|
|
9
9
|
[![license: MIT][license-badge]][license-url]
|
|
10
|
-
[![coverage][coverage-badge]][coverage-url]
|
|
10
|
+
[![test coverage][coverage-badge]][coverage-url]
|
|
11
11
|
[![ESM/CommonJS][modules-badge]][npm-url]
|
|
12
|
+
[](https://snyk.io/test/npm/metalsmith-optimize-images)
|
|
12
13
|
|
|
13
14
|
## Features
|
|
14
15
|
|
|
15
16
|
- **Multiple image formats**: Generates AVIF and WebP variants with JPEG/PNG fallbacks
|
|
16
17
|
- **Responsive sizes**: Creates different image sizes for various device widths
|
|
18
|
+
- **Background image support**: Automatically processes unused images for CSS `image-set()` backgrounds
|
|
19
|
+
- **Progressive loading**: Optional progressive image loading with low-quality placeholders
|
|
17
20
|
- **Lazy loading**: Uses native browser lazy loading for better performance
|
|
18
21
|
- **Content-based hashing**: Adds hash to filenames for optimal caching
|
|
19
22
|
- **Layout shift prevention**: Adds width/height attributes
|
|
20
23
|
- **Parallel processing**: Processes images in parallel for faster builds
|
|
21
|
-
- **Metadata generation**: Creates a JSON
|
|
24
|
+
- **Metadata generation**: Creates a JSON manifest with image information and variants
|
|
22
25
|
- **Configurable compression**: Customize compression settings per format
|
|
26
|
+
- **ESM and CommonJS support**:
|
|
27
|
+
- ESM: `import optimizeImages from 'metalsmith-optimize-images'`
|
|
28
|
+
- CommonJS: `const optimizeImages = require('metalsmith-optimize-images')`
|
|
23
29
|
|
|
24
30
|
## Installation
|
|
25
31
|
|
|
@@ -27,60 +33,61 @@ Metalsmith plugin for generating responsive images with optimal formats
|
|
|
27
33
|
npm install metalsmith-optimize-images
|
|
28
34
|
```
|
|
29
35
|
|
|
30
|
-
|
|
36
|
+
## Requirements
|
|
31
37
|
|
|
32
|
-
- Node.js 18.0.0
|
|
33
|
-
- Metalsmith 2.5.0
|
|
38
|
+
- Node.js >=18.0.0
|
|
39
|
+
- Metalsmith >=2.5.0
|
|
34
40
|
|
|
35
|
-
##
|
|
41
|
+
## Platform Testing Status
|
|
36
42
|
|
|
37
|
-
|
|
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
|
|
38
47
|
|
|
39
|
-
|
|
40
|
-
import metalsmith from 'metalsmith';
|
|
41
|
-
import optimizeImages from 'metalsmith-optimize-images';
|
|
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)!
|
|
42
49
|
|
|
43
|
-
|
|
44
|
-
optimizeImages({
|
|
45
|
-
// configuration options
|
|
46
|
-
widths: [320, 640, 960, 1280, 1920],
|
|
47
|
-
formats: ['avif', 'webp', 'original']
|
|
48
|
-
})
|
|
49
|
-
);
|
|
50
|
-
```
|
|
50
|
+
## Usage
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
> This plugin **must** be run after assets are copied but before any final HTML processing.
|
|
53
53
|
|
|
54
54
|
```javascript
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
55
|
+
metalsmith
|
|
56
|
+
.use(
|
|
57
|
+
assets({
|
|
58
|
+
source: 'lib/assets/', // Where to find assets
|
|
59
|
+
destination: 'assets/' // Where to copy assets
|
|
60
|
+
})
|
|
61
|
+
)
|
|
62
|
+
.use(
|
|
63
|
+
optimizeImages({
|
|
64
|
+
// configuration options
|
|
65
|
+
widths: [320, 640, 960, 1280, 1920],
|
|
66
|
+
formats: ['avif', 'webp', 'original']
|
|
67
|
+
})
|
|
68
|
+
);
|
|
65
69
|
```
|
|
66
70
|
|
|
67
71
|
## Options
|
|
68
72
|
|
|
69
|
-
| Option | Type | Default | Description
|
|
70
|
-
| --------------------- | ---------- | ------------------------------------- |
|
|
71
|
-
| `widths` | `number[]` | `[320, 640, 960, 1280, 1920]` | Image sizes to generate
|
|
72
|
-
| `formats` | `string[]` | `['avif', 'webp', 'original']` | Image formats in order of preference
|
|
73
|
-
| `formatOptions` | `object` | See below | Format-specific compression settings
|
|
74
|
-
| `htmlPattern` | `string` | `**/*.html` | Glob pattern to match HTML files
|
|
75
|
-
| `imgSelector` | `string` | `img:not([data-no-responsive])` | CSS selector for images to process
|
|
76
|
-
| `outputDir` | `string` | `assets/images/responsive` | Where to store the responsive images
|
|
77
|
-
| `outputPattern` | `string` | `[filename]-[width]w-[hash].[format]` | Filename pattern with tokens
|
|
78
|
-
| `skipLarger` | `boolean` | `true` | Don't upscale images
|
|
79
|
-
| `lazy` | `boolean` | `true` | Use native lazy loading
|
|
80
|
-
| `dimensionAttributes` | `boolean` | `true` | Add width/height to prevent layout shift
|
|
81
|
-
| `sizes` | `string` | `(max-width: 768px) 100vw, 75vw` | Default sizes attribute
|
|
82
|
-
| `concurrency` | `number` | `5` | Process N images at a time
|
|
83
|
-
| `generateMetadata` | `boolean` | `false` | Generate a metadata JSON file
|
|
73
|
+
| Option | Type | Default | Description |
|
|
74
|
+
| --------------------- | ---------- | ------------------------------------- | ------------------------------------------------------------------------------ |
|
|
75
|
+
| `widths` | `number[]` | `[320, 640, 960, 1280, 1920]` | Image sizes to generate |
|
|
76
|
+
| `formats` | `string[]` | `['avif', 'webp', 'original']` | Image formats in order of preference |
|
|
77
|
+
| `formatOptions` | `object` | See below | Format-specific compression settings |
|
|
78
|
+
| `htmlPattern` | `string` | `**/*.html` | Glob pattern to match HTML files |
|
|
79
|
+
| `imgSelector` | `string` | `img:not([data-no-responsive])` | CSS selector for images to process |
|
|
80
|
+
| `outputDir` | `string` | `assets/images/responsive` | Where to store the responsive images |
|
|
81
|
+
| `outputPattern` | `string` | `[filename]-[width]w-[hash].[format]` | Filename pattern with tokens |
|
|
82
|
+
| `skipLarger` | `boolean` | `true` | Don't upscale images |
|
|
83
|
+
| `lazy` | `boolean` | `true` | Use native lazy loading |
|
|
84
|
+
| `dimensionAttributes` | `boolean` | `true` | Add width/height to prevent layout shift |
|
|
85
|
+
| `sizes` | `string` | `(max-width: 768px) 100vw, 75vw` | Default sizes attribute |
|
|
86
|
+
| `concurrency` | `number` | `5` | Process N images at a time |
|
|
87
|
+
| `generateMetadata` | `boolean` | `false` | Generate a metadata JSON file at `{outputDir}/responsive-images-manifest.json` |
|
|
88
|
+
| `isProgressive` | `boolean` | `false` | Enable progressive image loading |
|
|
89
|
+
| `placeholder` | `object` | See below | Placeholder image settings |
|
|
90
|
+
| `processUnusedImages` | `boolean` | `true` | Process unused images for background use |
|
|
84
91
|
|
|
85
92
|
### Default Format Options
|
|
86
93
|
|
|
@@ -93,9 +100,23 @@ metalsmith.use(
|
|
|
93
100
|
}
|
|
94
101
|
```
|
|
95
102
|
|
|
103
|
+
### Default Placeholder Options
|
|
104
|
+
|
|
105
|
+
```javascript
|
|
106
|
+
{
|
|
107
|
+
width: 50, // Width of placeholder image
|
|
108
|
+
quality: 30, // Quality of placeholder image
|
|
109
|
+
blur: 10 // Blur amount for placeholder
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
96
113
|
## How It Works
|
|
97
114
|
|
|
98
|
-
|
|
115
|
+
### Standard Mode (default)
|
|
116
|
+
|
|
117
|
+
The plugin operates in two phases:
|
|
118
|
+
|
|
119
|
+
**Phase 1: HTML-Referenced Images**
|
|
99
120
|
|
|
100
121
|
1. Scans HTML files for image tags
|
|
101
122
|
2. Processes each image to create multiple sizes and formats
|
|
@@ -104,6 +125,25 @@ The plugin:
|
|
|
104
125
|
5. Adds width/height attributes to prevent layout shifts
|
|
105
126
|
6. Implements native lazy loading for better performance
|
|
106
127
|
|
|
128
|
+
**Phase 2: Background Images (when `processUnusedImages: true`)**
|
|
129
|
+
|
|
130
|
+
1. Finds images that weren't processed in Phase 1
|
|
131
|
+
2. Generates 1x/2x variants (half size and original size) for retina displays
|
|
132
|
+
3. Creates all configured formats (AVIF, WebP, original)
|
|
133
|
+
4. Suitable for use with CSS `image-set()` for background images
|
|
134
|
+
|
|
135
|
+
### Progressive Mode (experimental)
|
|
136
|
+
|
|
137
|
+
When `isProgressive: true` is enabled:
|
|
138
|
+
|
|
139
|
+
1. Generates low-quality placeholder images (small, blurred)
|
|
140
|
+
2. Creates wrapper elements with both placeholder and high-resolution images
|
|
141
|
+
3. Uses Intersection Observer to load high-resolution images on demand
|
|
142
|
+
4. Implements smooth transitions between placeholder and final image
|
|
143
|
+
5. Uses modern `createImageBitmap()` for reliable format detection (AVIF/WebP support)
|
|
144
|
+
6. Maintains proper aspect ratios using original image dimensions
|
|
145
|
+
7. Provides CSS and JavaScript for progressive loading behavior
|
|
146
|
+
|
|
107
147
|
## Examples
|
|
108
148
|
|
|
109
149
|
### Basic usage with defaults
|
|
@@ -135,12 +175,36 @@ metalsmith.use(
|
|
|
135
175
|
// Custom output directory
|
|
136
176
|
outputDir: 'images/processed',
|
|
137
177
|
|
|
178
|
+
// Generate metadata manifest
|
|
179
|
+
generateMetadata: true, // Creates images/processed/responsive-images-manifest.json
|
|
180
|
+
|
|
138
181
|
// Don't add lazy loading
|
|
139
182
|
lazy: false
|
|
140
183
|
})
|
|
141
184
|
);
|
|
142
185
|
```
|
|
143
186
|
|
|
187
|
+
### Progressive loading configuration
|
|
188
|
+
|
|
189
|
+
```javascript
|
|
190
|
+
metalsmith.use(
|
|
191
|
+
optimizeImages({
|
|
192
|
+
// Enable progressive loading
|
|
193
|
+
isProgressive: true,
|
|
194
|
+
|
|
195
|
+
// Customize placeholder settings
|
|
196
|
+
placeholder: {
|
|
197
|
+
width: 40, // Smaller placeholder
|
|
198
|
+
quality: 20, // Lower quality for faster loading
|
|
199
|
+
blur: 15 // More blur for artistic effect
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
// Progressive mode works best with original format only
|
|
203
|
+
formats: ['original']
|
|
204
|
+
})
|
|
205
|
+
);
|
|
206
|
+
```
|
|
207
|
+
|
|
144
208
|
### Excluding specific images
|
|
145
209
|
|
|
146
210
|
Add the `data-no-responsive` attribute to any image you don't want processed:
|
|
@@ -149,46 +213,217 @@ Add the `data-no-responsive` attribute to any image you don't want processed:
|
|
|
149
213
|
<img src="image.jpg" data-no-responsive alt="This image won't be processed" />
|
|
150
214
|
```
|
|
151
215
|
|
|
152
|
-
##
|
|
216
|
+
## Background Images
|
|
153
217
|
|
|
154
|
-
|
|
218
|
+
The plugin automatically processes images that aren't referenced in HTML for use as CSS background images. This feature is enabled by default (`processUnusedImages: true`).
|
|
155
219
|
|
|
156
|
-
|
|
220
|
+
### How Background Processing Works
|
|
157
221
|
|
|
158
|
-
|
|
222
|
+
After processing HTML-referenced images, the plugin:
|
|
159
223
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
224
|
+
1. **Scans the Metalsmith files object** for all images
|
|
225
|
+
2. **Excludes already-processed images** (those found during HTML scanning)
|
|
226
|
+
3. **Excludes responsive variants** (generated images in the outputDir)
|
|
227
|
+
4. **Generates 1x/2x variants** using actual image dimensions:
|
|
228
|
+
- **1x variant**: Half the original size for regular displays
|
|
229
|
+
- **2x variant**: Original image size for retina displays (sharper on high-DPI screens)
|
|
230
|
+
5. **Creates all formats** (AVIF, WebP, original) for optimal browser support
|
|
231
|
+
6. **No HTML replacement** - you manually write CSS with `image-set()`
|
|
232
|
+
|
|
233
|
+
### Using Background Images with CSS
|
|
234
|
+
|
|
235
|
+
For an image like `images/hero.jpg` (1920x1080 pixels), the plugin generates variants like:
|
|
163
236
|
|
|
164
|
-
|
|
165
|
-
|
|
237
|
+
```
|
|
238
|
+
assets/images/responsive/hero-960w.avif (1x - half 960px width for regular displays)
|
|
239
|
+
assets/images/responsive/hero-1920w.avif (2x - original 1920px width, sharper on retina)
|
|
240
|
+
assets/images/responsive/hero-960w.webp (1x - half 960px width for regular displays)
|
|
241
|
+
assets/images/responsive/hero-1920w.webp (2x - original 1920px width, sharper on retina)
|
|
242
|
+
assets/images/responsive/hero-960w.jpg (1x - half 960px width for regular displays)
|
|
243
|
+
assets/images/responsive/hero-1920w.jpg (2x - original 1920px width, sharper on retina)
|
|
166
244
|
```
|
|
167
245
|
|
|
168
|
-
|
|
246
|
+
**Note**: Background images are generated **without hashes** for easier CSS authoring. HTML images still include hashes for cache-busting.
|
|
247
|
+
|
|
248
|
+
Use them in CSS with `image-set()`:
|
|
249
|
+
|
|
250
|
+
```css
|
|
251
|
+
.hero {
|
|
252
|
+
background-image: image-set(
|
|
253
|
+
url('/assets/images/responsive/hero-960w.avif') 1x,
|
|
254
|
+
url('/assets/images/responsive/hero-1920w.avif') 2x,
|
|
255
|
+
url('/assets/images/responsive/hero-960w.webp') 1x,
|
|
256
|
+
url('/assets/images/responsive/hero-1920w.webp') 2x,
|
|
257
|
+
url('/assets/images/responsive/hero-960w.jpg') 1x,
|
|
258
|
+
url('/assets/images/responsive/hero-1920w.jpg') 2x
|
|
259
|
+
);
|
|
260
|
+
background-size: cover;
|
|
261
|
+
background-position: center;
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Background Image Configuration
|
|
169
266
|
|
|
170
267
|
```javascript
|
|
171
|
-
|
|
268
|
+
metalsmith.use(
|
|
269
|
+
optimizeImages({
|
|
270
|
+
// Standard HTML image processing
|
|
271
|
+
widths: [320, 640, 960, 1280, 1920],
|
|
272
|
+
formats: ['avif', 'webp', 'original'],
|
|
273
|
+
|
|
274
|
+
// Background image processing
|
|
275
|
+
processUnusedImages: true, // Enable background processing
|
|
172
276
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
277
|
+
// Generate metadata to see all variants
|
|
278
|
+
generateMetadata: true
|
|
279
|
+
})
|
|
280
|
+
);
|
|
177
281
|
```
|
|
178
282
|
|
|
179
|
-
|
|
283
|
+
### Benefits of Background Image Processing
|
|
284
|
+
|
|
285
|
+
- **Automatic format optimization** - Browser selects best supported format
|
|
286
|
+
- **Retina display support** - 2x variants provide crisp images on high-DPI screens
|
|
287
|
+
- **Smart sizing** - Uses actual image dimensions instead of arbitrary widths
|
|
288
|
+
- **No manual work** - Plugin automatically finds and processes unused images in Metalsmith files object
|
|
289
|
+
- **Consistent workflow** - Same formats and quality settings as HTML images
|
|
290
|
+
- **Efficient processing** - Parallel processing of sizes and formats
|
|
291
|
+
|
|
292
|
+
## Progressive Loading
|
|
293
|
+
|
|
294
|
+
### Overview
|
|
295
|
+
|
|
296
|
+
Progressive loading provides a smooth user experience by:
|
|
297
|
+
|
|
298
|
+
1. **Immediate display**: Shows a low-quality placeholder instantly
|
|
299
|
+
2. **Smooth transitions**: Fades from placeholder to high-quality image
|
|
300
|
+
3. **Lazy loading**: Only loads high-resolution images when they enter the viewport
|
|
301
|
+
4. **Format optimization**: Automatically serves the best supported format
|
|
302
|
+
|
|
303
|
+
### Implementation
|
|
304
|
+
|
|
305
|
+
When progressive mode is enabled, the plugin:
|
|
306
|
+
|
|
307
|
+
- Generates small, blurred placeholder images
|
|
308
|
+
- Creates wrapper elements with proper aspect ratios
|
|
309
|
+
- Includes JavaScript for intersection observer-based loading
|
|
310
|
+
- Provides CSS for smooth transitions
|
|
311
|
+
|
|
312
|
+
### HTML Output
|
|
313
|
+
|
|
314
|
+
**Standard mode:**
|
|
315
|
+
|
|
316
|
+
```html
|
|
317
|
+
<picture>
|
|
318
|
+
<source
|
|
319
|
+
type="image/avif"
|
|
320
|
+
srcset="image-320w.avif 320w, image-640w.avif 640w"
|
|
321
|
+
sizes="(max-width: 768px) 100vw, 75vw"
|
|
322
|
+
/>
|
|
323
|
+
<source
|
|
324
|
+
type="image/webp"
|
|
325
|
+
srcset="image-320w.webp 320w, image-640w.webp 640w"
|
|
326
|
+
sizes="(max-width: 768px) 100vw, 75vw"
|
|
327
|
+
/>
|
|
328
|
+
<img
|
|
329
|
+
src="image-640w.jpg"
|
|
330
|
+
srcset="image-320w.jpg 320w, image-640w.jpg 640w"
|
|
331
|
+
sizes="(max-width: 768px) 100vw, 75vw"
|
|
332
|
+
alt="Description"
|
|
333
|
+
loading="lazy"
|
|
334
|
+
/>
|
|
335
|
+
</picture>
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
**Progressive mode:**
|
|
339
|
+
|
|
340
|
+
```html
|
|
341
|
+
<div class="responsive-wrapper js-progressive-image-wrapper" style="aspect-ratio: 1280/720">
|
|
342
|
+
<img class="low-res" src="/assets/images/responsive/image-placeholder.jpg" alt="Description" />
|
|
343
|
+
<img class="high-res" src="" alt="Description" data-source="/assets/images/responsive/image-960w.jpg" />
|
|
344
|
+
</div>
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### CSS Requirements
|
|
348
|
+
|
|
349
|
+
The plugin provides CSS for progressive loading, but you can customize it:
|
|
350
|
+
|
|
351
|
+
```css
|
|
352
|
+
.responsive-wrapper {
|
|
353
|
+
position: relative;
|
|
354
|
+
overflow: hidden;
|
|
355
|
+
background-color: #f0f0f0;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.responsive-wrapper .low-res {
|
|
359
|
+
position: absolute;
|
|
360
|
+
top: 0;
|
|
361
|
+
left: 0;
|
|
362
|
+
width: 100%;
|
|
363
|
+
height: 100%;
|
|
364
|
+
object-fit: cover;
|
|
365
|
+
transition: opacity 0.4s ease;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
.responsive-wrapper .high-res {
|
|
369
|
+
position: absolute;
|
|
370
|
+
top: 0;
|
|
371
|
+
left: 0;
|
|
372
|
+
width: 100%;
|
|
373
|
+
height: 100%;
|
|
374
|
+
object-fit: cover;
|
|
375
|
+
opacity: 0;
|
|
376
|
+
transition: opacity 0.4s ease;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
.responsive-wrapper.done .high-res {
|
|
380
|
+
opacity: 1;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
.responsive-wrapper.done .low-res {
|
|
384
|
+
opacity: 0;
|
|
385
|
+
}
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
## Metadata Manifest
|
|
389
|
+
|
|
390
|
+
When `generateMetadata: true` is enabled, the plugin creates a JSON file at `{outputDir}/responsive-images-manifest.json` containing detailed information about all processed images:
|
|
180
391
|
|
|
181
392
|
```json
|
|
182
393
|
{
|
|
183
|
-
"
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
"
|
|
394
|
+
"images/hero.jpg": [
|
|
395
|
+
{
|
|
396
|
+
"path": "assets/images/responsive/hero-320w-a1b2c3d4.avif",
|
|
397
|
+
"width": 320,
|
|
398
|
+
"height": 180,
|
|
399
|
+
"format": "avif",
|
|
400
|
+
"size": 8432
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
"path": "assets/images/responsive/hero-320w-a1b2c3d4.webp",
|
|
404
|
+
"width": 320,
|
|
405
|
+
"height": 180,
|
|
406
|
+
"format": "webp",
|
|
407
|
+
"size": 12658
|
|
187
408
|
}
|
|
188
|
-
|
|
409
|
+
]
|
|
189
410
|
}
|
|
190
411
|
```
|
|
191
412
|
|
|
413
|
+
This manifest is useful for:
|
|
414
|
+
|
|
415
|
+
- **Debugging**: Verify which variants were generated
|
|
416
|
+
- **Integration**: Use variant information in other tools
|
|
417
|
+
- **Performance analysis**: Compare file sizes across formats
|
|
418
|
+
|
|
419
|
+
## Debug
|
|
420
|
+
|
|
421
|
+
To enable debug logs, set the DEBUG environment variable to metalsmith-optimize-images\*:
|
|
422
|
+
|
|
423
|
+
```javascript
|
|
424
|
+
metalsmith.env('DEBUG', 'metalsmith-optimize-images*');
|
|
425
|
+
```
|
|
426
|
+
|
|
192
427
|
## CLI Usage
|
|
193
428
|
|
|
194
429
|
### Metalsmith CLI
|
|
@@ -204,6 +439,36 @@ Or with the CLI:
|
|
|
204
439
|
}
|
|
205
440
|
```
|
|
206
441
|
|
|
442
|
+
## Recent Updates
|
|
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
|
|
462
|
+
|
|
463
|
+
### Current Status
|
|
464
|
+
|
|
465
|
+
- ✅ 95.27% test coverage with comprehensive edge case handling
|
|
466
|
+
- ✅ Real Metalsmith integration tests (no mocks)
|
|
467
|
+
- ✅ Tested on macOS with Node.js 18+
|
|
468
|
+
- 🔄 Seeking broader platform validation
|
|
469
|
+
|
|
470
|
+
**Report issues or success stories**: [GitHub Issues](https://github.com/wernerglinka/metalsmith-optimize-images/issues)
|
|
471
|
+
|
|
207
472
|
## License
|
|
208
473
|
|
|
209
474
|
MIT
|
|
@@ -215,5 +480,5 @@ MIT
|
|
|
215
480
|
[license-badge]: https://img.shields.io/github/license/wernerglinka/metalsmith-optimize-images
|
|
216
481
|
[license-url]: LICENSE
|
|
217
482
|
[coverage-badge]: https://img.shields.io/badge/test%20coverage-95%25-brightgreen
|
|
218
|
-
[coverage-url]:
|
|
483
|
+
[coverage-url]: https://github.com/wernerglinka/metalsmith-optimize-images/actions/workflows/test.yml
|
|
219
484
|
[modules-badge]: https://img.shields.io/badge/modules-ESM%2FCJS-blue
|