tischlerei-staffenberger/scripts/optimize-images.js
mrwhiski f2507033c3 Real contact/Impressum data, SEO tags, responsive gallery images, a11y and templating fixes
- Impressum rewritten with real Austrian business data (ECG instead of
  German TMG references); UID, Gewerbeberechtigung and Firmenbuchnummer
  marked as pending until available
- Real contact email/phone/address across footer and Impressum
- Meta description, Open Graph tags and favicon on all pages
- Gallery images now offer both 800w and 1920w srcset candidates
- Lightbox traps focus while open and restores it on close
- Header/footer extracted into partials/, pages now built from
  templates/ via `npm run build` (scripts/build.js) to remove
  duplication across the 4 pages
2026-07-12 18:11:11 +02:00

89 lines
2.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 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 = [
['kitchen', 'kitchen'],
['outdoor', 'outdoor'],
['custom', 'custom'],
];
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);
});