metalsmith-optimize-images 0.1.1 → 0.9.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 +192 -57
- package/lib/index.cjs +649 -66
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +648 -65
- package/lib/index.js.map +1 -1
- package/package.json +3 -5
package/README.md
CHANGED
|
@@ -1,25 +1,30 @@
|
|
|
1
1
|
# metalsmith-optimize-images
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> **🚀 Release Candidate**: This plugin has achieved comprehensive test coverage (96.06%) and is ready for production testing. 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
|
+
- **Progressive loading**: Optional progressive image loading with low-quality placeholders
|
|
17
19
|
- **Lazy loading**: Uses native browser lazy loading for better performance
|
|
18
20
|
- **Content-based hashing**: Adds hash to filenames for optimal caching
|
|
19
21
|
- **Layout shift prevention**: Adds width/height attributes
|
|
20
22
|
- **Parallel processing**: Processes images in parallel for faster builds
|
|
21
23
|
- **Metadata generation**: Creates a JSON file with image information
|
|
22
24
|
- **Configurable compression**: Customize compression settings per format
|
|
25
|
+
- **ESM and CommonJS support**:
|
|
26
|
+
- ESM: `import optimizeImages from 'metalsmith-optimize-images'`
|
|
27
|
+
- CommonJS: `const optimizeImages = require('metalsmith-optimize-images')`
|
|
23
28
|
|
|
24
29
|
## Installation
|
|
25
30
|
|
|
@@ -27,41 +32,39 @@ Metalsmith plugin for generating responsive images with optimal formats
|
|
|
27
32
|
npm install metalsmith-optimize-images
|
|
28
33
|
```
|
|
29
34
|
|
|
30
|
-
|
|
35
|
+
## Requirements
|
|
31
36
|
|
|
32
|
-
- Node.js 18.0.0
|
|
33
|
-
- Metalsmith 2.5.0
|
|
37
|
+
- Node.js >=18.0.0
|
|
38
|
+
- Metalsmith >=2.5.0
|
|
34
39
|
|
|
35
|
-
##
|
|
40
|
+
## Platform Testing Status
|
|
36
41
|
|
|
37
|
-
|
|
42
|
+
- ✅ **macOS**: Fully tested and working
|
|
43
|
+
- 🔄 **Windows**: Seeking community feedback on Sharp.js compatibility
|
|
44
|
+
- 🔄 **Linux**: Seeking validation across different distributions
|
|
45
|
+
- 🔄 **CI/CD**: Testing in various containerized environments
|
|
38
46
|
|
|
39
|
-
|
|
40
|
-
import metalsmith from 'metalsmith';
|
|
41
|
-
import optimizeImages from 'metalsmith-optimize-images';
|
|
47
|
+
**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
48
|
|
|
43
|
-
|
|
44
|
-
optimizeImages({
|
|
45
|
-
// configuration options
|
|
46
|
-
widths: [320, 640, 960, 1280, 1920],
|
|
47
|
-
formats: ['avif', 'webp', 'original']
|
|
48
|
-
})
|
|
49
|
-
);
|
|
50
|
-
```
|
|
49
|
+
## Usage
|
|
51
50
|
|
|
52
|
-
|
|
51
|
+
> This plugin **must** be run after assets are copied but before any final HTML processing.
|
|
53
52
|
|
|
54
53
|
```javascript
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
54
|
+
metalsmith
|
|
55
|
+
.use(
|
|
56
|
+
assets({
|
|
57
|
+
source: 'lib/assets/', // Where to find assets
|
|
58
|
+
destination: 'assets/' // Where to copy assets
|
|
59
|
+
})
|
|
60
|
+
)
|
|
61
|
+
.use(
|
|
62
|
+
optimizeImages({
|
|
63
|
+
// configuration options
|
|
64
|
+
widths: [320, 640, 960, 1280, 1920],
|
|
65
|
+
formats: ['avif', 'webp', 'original']
|
|
66
|
+
})
|
|
67
|
+
);
|
|
65
68
|
```
|
|
66
69
|
|
|
67
70
|
## Options
|
|
@@ -81,6 +84,8 @@ metalsmith.use(
|
|
|
81
84
|
| `sizes` | `string` | `(max-width: 768px) 100vw, 75vw` | Default sizes attribute |
|
|
82
85
|
| `concurrency` | `number` | `5` | Process N images at a time |
|
|
83
86
|
| `generateMetadata` | `boolean` | `false` | Generate a metadata JSON file |
|
|
87
|
+
| `isProgressive` | `boolean` | `false` | Enable progressive image loading |
|
|
88
|
+
| `placeholder` | `object` | See below | Placeholder image settings |
|
|
84
89
|
|
|
85
90
|
### Default Format Options
|
|
86
91
|
|
|
@@ -93,8 +98,20 @@ metalsmith.use(
|
|
|
93
98
|
}
|
|
94
99
|
```
|
|
95
100
|
|
|
101
|
+
### Default Placeholder Options
|
|
102
|
+
|
|
103
|
+
```javascript
|
|
104
|
+
{
|
|
105
|
+
width: 50, // Width of placeholder image
|
|
106
|
+
quality: 30, // Quality of placeholder image
|
|
107
|
+
blur: 10 // Blur amount for placeholder
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
96
111
|
## How It Works
|
|
97
112
|
|
|
113
|
+
### Standard Mode (default)
|
|
114
|
+
|
|
98
115
|
The plugin:
|
|
99
116
|
|
|
100
117
|
1. Scans HTML files for image tags
|
|
@@ -104,6 +121,18 @@ The plugin:
|
|
|
104
121
|
5. Adds width/height attributes to prevent layout shifts
|
|
105
122
|
6. Implements native lazy loading for better performance
|
|
106
123
|
|
|
124
|
+
### Progressive Mode (experimental)
|
|
125
|
+
|
|
126
|
+
When `isProgressive: true` is enabled:
|
|
127
|
+
|
|
128
|
+
1. Generates low-quality placeholder images (small, blurred)
|
|
129
|
+
2. Creates wrapper elements with both placeholder and high-resolution images
|
|
130
|
+
3. Uses Intersection Observer to load high-resolution images on demand
|
|
131
|
+
4. Implements smooth transitions between placeholder and final image
|
|
132
|
+
5. Uses modern `createImageBitmap()` for reliable format detection (AVIF/WebP support)
|
|
133
|
+
6. Maintains proper aspect ratios using original image dimensions
|
|
134
|
+
7. Provides CSS and JavaScript for progressive loading behavior
|
|
135
|
+
|
|
107
136
|
## Examples
|
|
108
137
|
|
|
109
138
|
### Basic usage with defaults
|
|
@@ -141,6 +170,27 @@ metalsmith.use(
|
|
|
141
170
|
);
|
|
142
171
|
```
|
|
143
172
|
|
|
173
|
+
### Progressive loading configuration
|
|
174
|
+
|
|
175
|
+
```javascript
|
|
176
|
+
metalsmith.use(
|
|
177
|
+
optimizeImages({
|
|
178
|
+
// Enable progressive loading
|
|
179
|
+
isProgressive: true,
|
|
180
|
+
|
|
181
|
+
// Customize placeholder settings
|
|
182
|
+
placeholder: {
|
|
183
|
+
width: 40, // Smaller placeholder
|
|
184
|
+
quality: 20, // Lower quality for faster loading
|
|
185
|
+
blur: 15 // More blur for artistic effect
|
|
186
|
+
},
|
|
187
|
+
|
|
188
|
+
// Progressive mode works best with original format only
|
|
189
|
+
formats: ['original']
|
|
190
|
+
})
|
|
191
|
+
);
|
|
192
|
+
```
|
|
193
|
+
|
|
144
194
|
### Excluding specific images
|
|
145
195
|
|
|
146
196
|
Add the `data-no-responsive` attribute to any image you don't want processed:
|
|
@@ -149,46 +199,110 @@ Add the `data-no-responsive` attribute to any image you don't want processed:
|
|
|
149
199
|
<img src="image.jpg" data-no-responsive alt="This image won't be processed" />
|
|
150
200
|
```
|
|
151
201
|
|
|
152
|
-
##
|
|
202
|
+
## Progressive Loading
|
|
153
203
|
|
|
154
|
-
|
|
204
|
+
### Overview
|
|
155
205
|
|
|
156
|
-
|
|
206
|
+
Progressive loading provides a smooth user experience by:
|
|
157
207
|
|
|
158
|
-
|
|
208
|
+
1. **Immediate display**: Shows a low-quality placeholder instantly
|
|
209
|
+
2. **Smooth transitions**: Fades from placeholder to high-quality image
|
|
210
|
+
3. **Lazy loading**: Only loads high-resolution images when they enter the viewport
|
|
211
|
+
4. **Format optimization**: Automatically serves the best supported format
|
|
159
212
|
|
|
160
|
-
|
|
161
|
-
// Enable debug output by setting the DEBUG environment variable
|
|
162
|
-
// DEBUG=metalsmith-responsive-images node build.js
|
|
213
|
+
### Implementation
|
|
163
214
|
|
|
164
|
-
|
|
165
|
-
// other plugins...
|
|
166
|
-
```
|
|
215
|
+
When progressive mode is enabled, the plugin:
|
|
167
216
|
|
|
168
|
-
|
|
217
|
+
- Generates small, blurred placeholder images
|
|
218
|
+
- Creates wrapper elements with proper aspect ratios
|
|
219
|
+
- Includes JavaScript for intersection observer-based loading
|
|
220
|
+
- Provides CSS for smooth transitions
|
|
169
221
|
|
|
170
|
-
|
|
171
|
-
|
|
222
|
+
### HTML Output
|
|
223
|
+
|
|
224
|
+
**Standard mode:**
|
|
172
225
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
226
|
+
```html
|
|
227
|
+
<picture>
|
|
228
|
+
<source
|
|
229
|
+
type="image/avif"
|
|
230
|
+
srcset="image-320w.avif 320w, image-640w.avif 640w"
|
|
231
|
+
sizes="(max-width: 768px) 100vw, 75vw"
|
|
232
|
+
/>
|
|
233
|
+
<source
|
|
234
|
+
type="image/webp"
|
|
235
|
+
srcset="image-320w.webp 320w, image-640w.webp 640w"
|
|
236
|
+
sizes="(max-width: 768px) 100vw, 75vw"
|
|
237
|
+
/>
|
|
238
|
+
<img
|
|
239
|
+
src="image-640w.jpg"
|
|
240
|
+
srcset="image-320w.jpg 320w, image-640w.jpg 640w"
|
|
241
|
+
sizes="(max-width: 768px) 100vw, 75vw"
|
|
242
|
+
alt="Description"
|
|
243
|
+
loading="lazy"
|
|
244
|
+
/>
|
|
245
|
+
</picture>
|
|
177
246
|
```
|
|
178
247
|
|
|
179
|
-
|
|
248
|
+
**Progressive mode:**
|
|
180
249
|
|
|
181
|
-
```
|
|
182
|
-
|
|
183
|
-
"
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
250
|
+
```html
|
|
251
|
+
<div class="responsive-wrapper js-progressive-image-wrapper" style="aspect-ratio: 1280/720">
|
|
252
|
+
<img class="low-res" src="/assets/images/responsive/image-placeholder.jpg" alt="Description" />
|
|
253
|
+
<img class="high-res" src="" alt="Description" data-source="/assets/images/responsive/image-960w.jpg" />
|
|
254
|
+
</div>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### CSS Requirements
|
|
258
|
+
|
|
259
|
+
The plugin provides CSS for progressive loading, but you can customize it:
|
|
260
|
+
|
|
261
|
+
```css
|
|
262
|
+
.responsive-wrapper {
|
|
263
|
+
position: relative;
|
|
264
|
+
overflow: hidden;
|
|
265
|
+
background-color: #f0f0f0;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.responsive-wrapper .low-res {
|
|
269
|
+
position: absolute;
|
|
270
|
+
top: 0;
|
|
271
|
+
left: 0;
|
|
272
|
+
width: 100%;
|
|
273
|
+
height: 100%;
|
|
274
|
+
object-fit: cover;
|
|
275
|
+
transition: opacity 0.4s ease;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.responsive-wrapper .high-res {
|
|
279
|
+
position: absolute;
|
|
280
|
+
top: 0;
|
|
281
|
+
left: 0;
|
|
282
|
+
width: 100%;
|
|
283
|
+
height: 100%;
|
|
284
|
+
object-fit: cover;
|
|
285
|
+
opacity: 0;
|
|
286
|
+
transition: opacity 0.4s ease;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
.responsive-wrapper.done .high-res {
|
|
290
|
+
opacity: 1;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
.responsive-wrapper.done .low-res {
|
|
294
|
+
opacity: 0;
|
|
189
295
|
}
|
|
190
296
|
```
|
|
191
297
|
|
|
298
|
+
## Debug
|
|
299
|
+
|
|
300
|
+
To enable debug logs, set the DEBUG environment variable to metalsmith-optimize-images\*:
|
|
301
|
+
|
|
302
|
+
```javascript
|
|
303
|
+
metalsmith.env('DEBUG', 'metalsmith-optimize-images*');
|
|
304
|
+
```
|
|
305
|
+
|
|
192
306
|
## CLI Usage
|
|
193
307
|
|
|
194
308
|
### Metalsmith CLI
|
|
@@ -204,6 +318,27 @@ Or with the CLI:
|
|
|
204
318
|
}
|
|
205
319
|
```
|
|
206
320
|
|
|
321
|
+
## Feedback & Testing
|
|
322
|
+
|
|
323
|
+
This plugin is approaching 1.0.0 and we'd love your feedback! Please test and report:
|
|
324
|
+
|
|
325
|
+
### Especially Needed
|
|
326
|
+
|
|
327
|
+
- **Windows compatibility**: Sharp.js native compilation and image processing
|
|
328
|
+
- **Large image batches**: Performance with 50+ images
|
|
329
|
+
- **Memory usage**: Resource consumption in your environment
|
|
330
|
+
- **Cross-platform consistency**: Image quality and file sizes across platforms
|
|
331
|
+
- **Progressive loading**: Behavior across different browsers
|
|
332
|
+
|
|
333
|
+
### Current Status
|
|
334
|
+
|
|
335
|
+
- ✅ 96.06% test coverage with comprehensive edge case handling
|
|
336
|
+
- ✅ Real Metalsmith integration tests (no mocks)
|
|
337
|
+
- ✅ Tested on macOS with Node.js 18+
|
|
338
|
+
- 🔄 Seeking broader platform validation
|
|
339
|
+
|
|
340
|
+
**Report issues or success stories**: [GitHub Issues](https://github.com/wernerglinka/metalsmith-optimize-images/issues)
|
|
341
|
+
|
|
207
342
|
## License
|
|
208
343
|
|
|
209
344
|
MIT
|
|
@@ -214,6 +349,6 @@ MIT
|
|
|
214
349
|
[metalsmith-url]: https://metalsmith.io
|
|
215
350
|
[license-badge]: https://img.shields.io/github/license/wernerglinka/metalsmith-optimize-images
|
|
216
351
|
[license-url]: LICENSE
|
|
217
|
-
[coverage-badge]: https://img.shields.io/badge/test%20coverage-
|
|
218
|
-
[coverage-url]:
|
|
352
|
+
[coverage-badge]: https://img.shields.io/badge/test%20coverage-96%25-brightgreen
|
|
353
|
+
[coverage-url]: https://github.com/wernerglinka/metalsmith-optimize-images/actions/workflows/test.yml
|
|
219
354
|
[modules-badge]: https://img.shields.io/badge/modules-ESM%2FCJS-blue
|