#!/usr/bin/env node import { promises as fs } from 'fs' import path from 'path' import sharp from 'sharp' const cwd = process.cwd() const outputRoot = path.join(cwd, 'public', 'images', 'hero') const inputRoots = [ path.join(cwd, 'assets', 'images', 'hero-originals'), path.join(cwd, 'public', 'images', 'hero-originals') ] const OUTPUT_VARIANTS = [ { width: 960, height: 540, quality: 66, fileName: 'hero_960.webp' }, { width: 1600, height: 900, quality: 72, fileName: 'hero_1600.webp' } ] async function ensureDir(dirPath) { await fs.mkdir(dirPath, { recursive: true }) } async function listSubdirs(rootPath) { const entries = await fs.readdir(rootPath, { withFileTypes: true }) return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name) } async function listFiles(rootPath) { const entries = await fs.readdir(rootPath, { withFileTypes: true }) return entries.filter((entry) => entry.isFile()).map((entry) => entry.name) } function normalizeVariantName(name) { return String(name || '') .trim() .toLowerCase() .replace(/[^a-z0-9_-]+/g, '-') .replace(/-+/g, '-') .replace(/^-|-$/g, '') || 'hero' } function pickSourcePng(files) { const pngFiles = files.filter((file) => /\.png$/i.test(file)) if (!pngFiles.length) return null const prioritized = ['hero.png', 'hero-original.png', 'original.png'] for (const name of prioritized) { const found = pngFiles.find((file) => file.toLowerCase() === name) if (found) return found } return pngFiles.sort((a, b) => a.localeCompare(b, 'de'))[0] } async function convertVariant(sourcePath, targetDir, variant) { const targetPath = path.join(targetDir, variant.fileName) await sharp(sourcePath) .resize(variant.width, variant.height, { fit: 'cover', position: 'centre' }) .webp({ quality: variant.quality }) .toFile(targetPath) } async function collectVariantSources(rootPath) { const sources = [] const subdirs = await listSubdirs(rootPath) for (const dirName of subdirs.sort((a, b) => a.localeCompare(b, 'de'))) { const dirPath = path.join(rootPath, dirName) const files = await fs.readdir(dirPath) const sourceFile = pickSourcePng(files) if (!sourceFile) continue sources.push({ variant: normalizeVariantName(dirName), sourcePath: path.join(dirPath, sourceFile) }) } if (sources.length) return sources const rootFiles = await listFiles(rootPath) const pngFiles = rootFiles.filter((file) => /\.png$/i.test(file)).sort((a, b) => a.localeCompare(b, 'de')) for (const fileName of pngFiles) { sources.push({ variant: normalizeVariantName(path.parse(fileName).name), sourcePath: path.join(rootPath, fileName) }) } return sources } async function findInputRootWithSources() { for (const rootPath of inputRoots) { try { const stats = await fs.stat(rootPath) if (!stats.isDirectory()) continue const sources = await collectVariantSources(rootPath) if (sources.length) { return { rootPath, sources } } } catch { // ignore missing roots } } return null } async function processVariantSource(source) { const targetDir = path.join(outputRoot, source.variant) await ensureDir(targetDir) for (const variant of OUTPUT_VARIANTS) { await convertVariant(source.sourcePath, targetDir, variant) } await fs.copyFile(source.sourcePath, path.join(targetDir, 'hero_fallback.png')) return { variant: source.variant, source: path.relative(cwd, source.sourcePath), target: path.relative(cwd, targetDir) } } async function main() { try { await ensureDir(outputRoot) const input = await findInputRootWithSources() if (!input) { console.error('Keine Hero-Quellen gefunden.') console.error('Unterstuetzte Pfade:') console.error(`- ${inputRoots[0]}//*.png`) console.error(`- ${inputRoots[1]}/*.png`) process.exit(1) } const results = [] for (const source of input.sources) { const result = await processVariantSource(source) results.push(result) } console.log(`Input-Quelle: ${path.relative(cwd, input.rootPath)}`) console.log('Hero-Varianten erfolgreich erstellt:') for (const result of results) { console.log(`- ${result.variant}: ${result.source} -> ${result.target}`) } } catch (error) { console.error('Fehler bei der Hero-Bildaufbereitung:', error) process.exit(1) } } await main()