Optimize CMS images during builds

This commit is contained in:
Kevin
2026-09-04 12:11:09 -04:00
parent 80dd0e0904
commit dd6fae06c9
11 changed files with 136 additions and 22 deletions
+17 -2
View File
@@ -1,5 +1,7 @@
import { access, readFile } from 'node:fs/promises';
import { resolve } from 'node:path';
import { access, readFile, readdir, stat } from 'node:fs/promises';
import { extname, resolve } from 'node:path';
import sharp from 'sharp';
import { allowedUploadExtensions, maxBuiltImageBytes, maxBuiltImageDimension } from './image-policy.mjs';
const key = process.env.SITE_KEY;
if (!key) throw new Error('SITE_KEY is required.');
@@ -31,6 +33,19 @@ if (!admin.includes('decap-cms@3.15.1/dist/decap-cms.js')) throw new Error('Admi
const headers = await readFile(resolve(root, '_headers'), 'utf8');
if (!/\/admin\/\*[\s\S]*X-Robots-Tag: noindex, nofollow, noarchive/.test(headers)) throw new Error('Admin response headers are missing the no-index rule.');
const builtUploads = resolve(root, 'images/uploads');
for (const entry of await readdir(builtUploads, { withFileTypes: true })) {
if (!entry.isFile()) throw new Error(`Built CMS media contains a nested or special path: ${entry.name}.`);
const extension = extname(entry.name).toLowerCase();
if (!allowedUploadExtensions.has(extension)) throw new Error(`Built CMS media has a disallowed extension: ${entry.name}.`);
const path = resolve(builtUploads, entry.name);
const info = await stat(path);
if (info.size > maxBuiltImageBytes) throw new Error(`Built CMS image exceeds ${maxBuiltImageBytes} bytes: ${entry.name}.`);
const metadata = await sharp(path).metadata();
if ((metadata.width ?? 0) > maxBuiltImageDimension || (metadata.height ?? 0) > maxBuiltImageDimension) throw new Error(`Built CMS image exceeds ${maxBuiltImageDimension}px: ${entry.name}.`);
if (metadata.exif || metadata.icc || metadata.iptc || metadata.xmp) throw new Error(`Built CMS image retained metadata: ${entry.name}.`);
}
const home = await readFile(resolve(root, 'index.html'), 'utf8');
if (key === 'www') {
for (const { file, html } of pages) if (!html.includes('href="https://blog.3031023.xyz/"')) throw new Error(`${file} is missing the Happy Tails Journal link.`);