fork of hey-api/openapi-ts because I need some additional things
1import fs from 'node:fs';
2import path from 'node:path';
3
4import sharp from 'sharp';
5
6const allowedImageExtensions = ['.png', '.jpg', '.jpeg', '.webp', '.svg'];
7const images = [
8 {
9 sizes: [
10 {
11 formats: ['png'],
12 width: 300,
13 },
14 {
15 formats: ['png'],
16 width: 640,
17 },
18 ],
19 source: 'blueprint.png',
20 },
21 {
22 sizes: [
23 {
24 formats: ['png'],
25 width: 300,
26 },
27 {
28 formats: ['png'],
29 width: 640,
30 },
31 ],
32 source: 'bricks.png',
33 },
34 {
35 sizes: [
36 {
37 formats: ['png'],
38 width: 300,
39 },
40 {
41 formats: ['png'],
42 width: 640,
43 },
44 {
45 formats: ['png'],
46 width: 920,
47 },
48 ],
49 source: 'hero.png',
50 },
51 {
52 sizes: [
53 {
54 formats: ['png'],
55 width: 300,
56 },
57 {
58 formats: ['png'],
59 width: 640,
60 },
61 {
62 formats: ['png'],
63 width: 1280,
64 },
65 ],
66 source: 'openapi-ts-hero.png',
67 },
68 {
69 sizes: [
70 {
71 formats: ['png'],
72 width: 16,
73 },
74 {
75 formats: ['png'],
76 width: 32,
77 },
78 {
79 formats: ['png'],
80 width: 48,
81 },
82 {
83 formats: ['png'],
84 width: 300,
85 },
86 {
87 formats: ['png'],
88 width: 640,
89 },
90 ],
91 source: 'logo.png',
92 },
93 {
94 sizes: [
95 {
96 formats: ['png'],
97 width: 300,
98 },
99 ],
100 source: 'logo-astronaut.png',
101 },
102 {
103 sizes: [
104 {
105 formats: ['jpeg', 'webp'],
106 width: 480,
107 },
108 {
109 formats: ['webp'],
110 width: 768,
111 },
112 {
113 formats: ['png', 'webp'],
114 width: 1200,
115 },
116 ],
117 source: 'cella-logo-wordmark.png',
118 },
119 {
120 sizes: [
121 {
122 formats: ['jpeg', 'webp'],
123 width: 480,
124 },
125 {
126 formats: ['webp'],
127 width: 768,
128 },
129 {
130 formats: ['png', 'webp'],
131 width: 1200,
132 },
133 ],
134 source: 'kinde-logo-wordmark.png',
135 },
136 {
137 sizes: [
138 {
139 formats: ['jpeg', 'webp'],
140 width: 480,
141 },
142 {
143 formats: ['webp'],
144 width: 768,
145 },
146 {
147 formats: ['png', 'webp'],
148 width: 1200,
149 },
150 ],
151 source: 'kinde-logo-wordmark-dark.png',
152 },
153 {
154 sizes: [
155 {
156 formats: ['jpeg', 'webp'],
157 width: 480,
158 },
159 {
160 formats: ['webp'],
161 width: 768,
162 },
163 {
164 formats: ['png', 'webp'],
165 width: 1200,
166 },
167 ],
168 source: 'openstatus-logo.svg',
169 },
170 {
171 sizes: [
172 {
173 formats: ['jpeg', 'webp'],
174 width: 480,
175 },
176 {
177 formats: ['webp'],
178 width: 768,
179 },
180 {
181 formats: ['png', 'webp'],
182 width: 1200,
183 },
184 ],
185 source: 'scalar-logo-wordmark.png',
186 },
187 {
188 sizes: [
189 {
190 formats: ['jpeg', 'webp'],
191 width: 480,
192 },
193 {
194 formats: ['webp'],
195 width: 768,
196 },
197 {
198 formats: ['png', 'webp'],
199 width: 1200,
200 },
201 ],
202 source: 'stainless-logo-wordmark.png',
203 },
204 {
205 sizes: [
206 {
207 formats: ['jpeg', 'webp'],
208 width: 480,
209 },
210 {
211 formats: ['webp'],
212 width: 768,
213 },
214 {
215 formats: ['png', 'webp'],
216 width: 1200,
217 },
218 ],
219 source: 'vercel-logo.svg',
220 },
221];
222
223const outputDir = 'public/images';
224
225if (fs.existsSync(outputDir)) {
226 fs.rmSync(outputDir, { force: true, recursive: true });
227}
228
229fs.mkdirSync(outputDir, { recursive: true });
230
231async function processImages() {
232 for (const image of images) {
233 const inputPath = path.join('public', image.source);
234 const ext = path.extname(image.source).toLowerCase();
235 const name = path.basename(image.source, ext);
236
237 if (!allowedImageExtensions.includes(ext)) {
238 continue;
239 }
240
241 for (const imageSize of image.sizes) {
242 const size = typeof imageSize === 'object' ? imageSize.width : imageSize;
243 const formats =
244 typeof imageSize === 'object'
245 ? imageSize.formats || image.formats
246 : image.formats;
247 for (const format of formats) {
248 const outputFileName = `${name}-${size}w.${format}`;
249 const outputPath = path.join(outputDir, outputFileName);
250
251 let image = sharp(inputPath).resize(size).toFormat(format, {
252 quality: 80,
253 });
254
255 if (format === 'jpeg') {
256 image = image.flatten({ background: '#ffffff' });
257 }
258
259 await image.toFile(outputPath);
260 }
261 }
262 }
263}
264
265processImages().catch((err) => {
266 console.error('❌ Error optimizing images:', err);
267});