139 lines
5.0 KiB
JavaScript
139 lines
5.0 KiB
JavaScript
const sharp = require('sharp');
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
async function createLogoWithText(faviconPath, outputPath, size) {
|
|
try {
|
|
// Load and resize favicon - smaller to leave room for text
|
|
const faviconSize = Math.floor(size * 0.65);
|
|
const faviconBuffer = await sharp(faviconPath)
|
|
.resize(faviconSize, faviconSize, {
|
|
fit: 'contain',
|
|
background: { r: 255, g: 255, b: 255, alpha: 0 }
|
|
})
|
|
.toBuffer();
|
|
|
|
// Create SVG with favicon and text
|
|
const textSize = Math.floor(size * 0.12);
|
|
const iconY = Math.floor(size * 0.10); // Logo higher up
|
|
const textY = Math.floor(size * 0.92); // Text further down
|
|
const iconX = Math.floor((size - faviconSize) / 2);
|
|
|
|
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<svg width="${size}" height="${size}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<!-- White background -->
|
|
<rect width="${size}" height="${size}" fill="#ffffff"/>
|
|
<image href="data:image/png;base64,${faviconBuffer.toString('base64')}"
|
|
x="${iconX}"
|
|
y="${iconY}"
|
|
width="${faviconSize}"
|
|
height="${faviconSize}"/>
|
|
<text x="${size / 2}" y="${textY}"
|
|
font-family="system-ui, -apple-system, sans-serif"
|
|
font-size="${textSize}"
|
|
font-weight="bold"
|
|
fill="#000000"
|
|
text-anchor="middle"
|
|
letter-spacing="-0.5">
|
|
hördle.de
|
|
</text>
|
|
</svg>`;
|
|
|
|
// Convert SVG to PNG with white background
|
|
await sharp(Buffer.from(svg))
|
|
.resize(size, size)
|
|
.png()
|
|
.toFile(outputPath);
|
|
|
|
console.log(`✅ Created ${path.basename(outputPath)} (${size}x${size})`);
|
|
} catch (error) {
|
|
console.error(`❌ Error creating ${outputPath}:`, error.message);
|
|
}
|
|
}
|
|
|
|
async function createSVGLogo(faviconPath, outputPath, size) {
|
|
try {
|
|
// Load and resize favicon - smaller to leave room for text
|
|
const faviconSize = Math.floor(size * 0.65);
|
|
const faviconBuffer = await sharp(faviconPath)
|
|
.resize(faviconSize, faviconSize, {
|
|
fit: 'contain',
|
|
background: { r: 255, g: 255, b: 255, alpha: 0 }
|
|
})
|
|
.toBuffer();
|
|
|
|
// Create SVG with favicon and text
|
|
const textSize = Math.floor(size * 0.12);
|
|
const iconY = Math.floor(size * 0.10); // Logo higher up
|
|
const textY = Math.floor(size * 0.92); // Text further down
|
|
const iconX = Math.floor((size - faviconSize) / 2);
|
|
|
|
const svg = `<?xml version="1.0" encoding="UTF-8"?>
|
|
<svg width="${size}" height="${size}" viewBox="0 0 ${size} ${size}" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
<!-- White background covering entire image -->
|
|
<rect width="${size}" height="${size}" fill="#ffffff"/>
|
|
<image href="data:image/png;base64,${faviconBuffer.toString('base64')}"
|
|
x="${iconX}"
|
|
y="${iconY}"
|
|
width="${faviconSize}"
|
|
height="${faviconSize}"/>
|
|
<text x="${size / 2}" y="${textY}"
|
|
font-family="system-ui, -apple-system, sans-serif"
|
|
font-size="${textSize}"
|
|
font-weight="bold"
|
|
fill="#000000"
|
|
text-anchor="middle"
|
|
letter-spacing="-0.5">
|
|
hördle.de
|
|
</text>
|
|
</svg>`;
|
|
|
|
fs.writeFileSync(outputPath, svg);
|
|
console.log(`✅ Created ${path.basename(outputPath)} (${size}x${size} SVG)`);
|
|
} catch (error) {
|
|
console.error(`❌ Error creating ${outputPath}:`, error.message);
|
|
}
|
|
}
|
|
|
|
async function main() {
|
|
const faviconPath = path.join(__dirname, '..', 'app', 'favicon.ico');
|
|
const publicDir = path.join(__dirname, '..', 'public');
|
|
|
|
if (!fs.existsSync(faviconPath)) {
|
|
console.error('❌ Favicon not found at', faviconPath);
|
|
return;
|
|
}
|
|
|
|
// Extract favicon to PNG first for processing
|
|
const tempFavicon = path.join(publicDir, 'favicon-temp.png');
|
|
const faviconBuffer = fs.readFileSync(faviconPath);
|
|
|
|
// Convert ICO to PNG
|
|
await sharp(faviconBuffer)
|
|
.resize(1024, 1024, { fit: 'contain' })
|
|
.png()
|
|
.toFile(tempFavicon);
|
|
|
|
console.log('✅ Extracted favicon to PNG\n');
|
|
|
|
// Create SVG logo
|
|
await createSVGLogo(tempFavicon, path.join(publicDir, 'logo.svg'), 512);
|
|
await createSVGLogo(tempFavicon, path.join(publicDir, 'logo-large.svg'), 1024);
|
|
|
|
// Create PNG logos with text in various sizes
|
|
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-128.png'), 128);
|
|
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-256.png'), 256);
|
|
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-512.png'), 512);
|
|
await createLogoWithText(tempFavicon, path.join(publicDir, 'logo-1024.png'), 1024);
|
|
|
|
// Clean up temp file
|
|
if (fs.existsSync(tempFavicon)) {
|
|
fs.unlinkSync(tempFavicon);
|
|
}
|
|
|
|
console.log('\n✨ Logo creation complete!');
|
|
}
|
|
|
|
main();
|
|
|