/** * Image optimization script for Tischlerei Staffenberger. * Generates WebP + JPEG variants at thumbnail (800px) and lightbox (1920px) sizes. * Output: images/optimized/{category}/{name}-{size}w.{ext} * * Run: node scripts/optimize-images.js */ 'use strict'; const sharp = require('sharp'); const fs = require('fs'); const path = require('path'); const PROJECT_ROOT = path.join(__dirname, '..'); const INPUT_ROOT = path.join(PROJECT_ROOT, 'images', 'fotowebsite'); const OUTPUT_ROOT = path.join(PROJECT_ROOT, 'images', 'optimized'); // Gallery categories: [input subdir, output subdir] const GALLERY_DIRS = [ ['küche', 'küche'], ['aussenbereich', 'aussenbereich'], ['sonderanfertigungen', 'sonderanfertigungen'], ]; const GALLERY_SIZES = [800, 1920]; const BANNER_SIZES = [800, 1920]; function safeName(filename) { return path.basename(filename, path.extname(filename)).replace(/\s+/g, '-'); } async function processImage(inputPath, outputDir, baseName, sizes) { fs.mkdirSync(outputDir, { recursive: true }); for (const width of sizes) { const jpegOut = path.join(outputDir, `${baseName}-${width}w.jpg`); const webpOut = path.join(outputDir, `${baseName}-${width}w.webp`); await sharp(inputPath) .resize({ width, withoutEnlargement: true }) .jpeg({ quality: 85, mozjpeg: true }) .toFile(jpegOut); await sharp(inputPath) .resize({ width, withoutEnlargement: true }) .webp({ quality: 82 }) .toFile(webpOut); const jpegSize = (fs.statSync(jpegOut).size / 1024).toFixed(0); const webpSize = (fs.statSync(webpOut).size / 1024).toFixed(0); console.log(` ${path.basename(jpegOut)}: JPEG ${jpegSize}KB WebP ${webpSize}KB`); } } async function main() { console.log('=== Tischlerei Staffenberger – Image Optimization ===\n'); // --- Gallery images --- for (const [inputSubdir, outputSubdir] of GALLERY_DIRS) { const inputDir = path.join(INPUT_ROOT, inputSubdir); const outputDir = path.join(OUTPUT_ROOT, outputSubdir); const files = fs.readdirSync(inputDir) .filter(f => /\.(jpe?g)$/i.test(f)) .sort(); console.log(`[${inputSubdir}] – ${files.length} images`); for (const file of files) { const inputPath = path.join(inputDir, file); const baseName = safeName(file); await processImage(inputPath, outputDir, baseName, GALLERY_SIZES); } } // --- Banner --- const bannerInput = path.join(INPUT_ROOT, 'banner.jpg'); const bannerOutput = OUTPUT_ROOT; console.log('\n[banner]'); await processImage(bannerInput, bannerOutput, 'banner', BANNER_SIZES); console.log('\nDone.'); } main().catch(err => { console.error(err); process.exit(1); });