93 lines
4.3 KiB
JavaScript
93 lines
4.3 KiB
JavaScript
const express = require('express');
|
|
const axios = require('axios');
|
|
|
|
const app = express();
|
|
const PORT = process.env.PORT || 3000;
|
|
|
|
app.get('/badge', async (req, res) => {
|
|
const {
|
|
icon = 'portainer',
|
|
label = 'Portainer',
|
|
bg = '#f0f0f0',
|
|
color = '#000000',
|
|
size = 24,
|
|
labelpos = 'right', // lehet: 'right', 'left', 'above', 'below'
|
|
fontweight = 'normal', // új paraméter, alapértelmezett: normal
|
|
} = req.query;
|
|
|
|
try {
|
|
// Ikon letöltése
|
|
const iconUrl = `https://cdn.simpleicons.org/${icon}?viewbox=auto&size=${size}`;
|
|
const iconResponse = await axios.get(iconUrl, { responseType: 'text' });
|
|
if (iconResponse.status !== 200) {
|
|
return res.status(404).send('Icon not found');
|
|
}
|
|
const iconSVG = iconResponse.data;
|
|
|
|
// Badge méretek
|
|
const padding = 10;
|
|
const iconSize = parseInt(size);
|
|
const fontSize = Math.round(iconSize * 0.6); // Font size az ikon méret 60%-a
|
|
const textPadding = Math.round(iconSize * 0.4); // Dinamikus: size 40%-a
|
|
const radius = 8;
|
|
const approxCharWidth = fontSize * 0.6;
|
|
const textWidth = label.length * approxCharWidth;
|
|
|
|
let width, height, iconGroup, textElem;
|
|
|
|
// Szebb, élsimított font shields.io stílusban
|
|
const fontFamily = "Verdana,Geneva,DejaVu Sans,sans-serif";
|
|
const fontWeight = fontweight; // paraméterből
|
|
|
|
if (labelpos === 'above' || labelpos === 'below') {
|
|
width = Math.max(iconSize, textWidth) + padding * 2;
|
|
height = padding * 2 + iconSize + textPadding + fontSize;
|
|
if (labelpos === 'above') {
|
|
// Szöveg felül, ikon alul
|
|
textElem = `<text x="${width / 2}" y="${padding + fontSize}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${color}" text-anchor="middle" dominant-baseline="middle">${label}</text>`;
|
|
iconGroup = `<g transform="translate(${(width - iconSize) / 2}, ${padding + fontSize + textPadding})">${iconSVG}</g>`;
|
|
} else {
|
|
// Szöveg alul, ikon felül
|
|
iconGroup = `<g transform="translate(${(width - iconSize) / 2}, ${padding})">${iconSVG}</g>`;
|
|
textElem = `<text x="${width / 2}" y="${padding + iconSize + textPadding}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${color}" text-anchor="middle" dominant-baseline="hanging">${label}</text>`;
|
|
}
|
|
} else if (labelpos === 'left') {
|
|
width = padding * 2 + iconSize + textPadding + textWidth;
|
|
height = Math.max(iconSize + padding * 2, fontSize + padding * 2);
|
|
// Szöveg balra, ikon jobbra (függőleges közép)
|
|
textElem = `<text x="${padding}" y="${height / 2}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${color}" alignment-baseline="middle" dominant-baseline="middle">${label}</text>`;
|
|
iconGroup = `<g transform="translate(${padding + textWidth + textPadding}, ${(height - iconSize) / 2})">${iconSVG}</g>`;
|
|
} else {
|
|
width = padding * 2 + iconSize + textPadding + textWidth;
|
|
height = Math.max(iconSize + padding * 2, fontSize + padding * 2);
|
|
// Alapértelmezett: ikon balra, szöveg jobbra (függőleges közép)
|
|
iconGroup = `<g transform="translate(${padding}, ${(height - iconSize) / 2})">${iconSVG}</g>`;
|
|
textElem = `<text x="${padding + iconSize + textPadding + textWidth / 2}" y="${height / 2}" font-size="${fontSize}" font-family="${fontFamily}" font-weight="${fontWeight}" fill="${color}" text-anchor="middle" dominant-baseline="middle">${label}</text>`;
|
|
}
|
|
|
|
// SVG badge string összefűzéssel, szöveg árnyékkal
|
|
const svg = `
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" style="background:none">
|
|
<defs>
|
|
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
|
|
<feDropShadow dx="0" dy="1" stdDeviation="1" flood-color="#000" flood-opacity="0.25"/>
|
|
</filter>
|
|
</defs>
|
|
<rect x="0" y="0" width="${width}" height="${height}" rx="${radius}" fill="${bg}"/>
|
|
${iconGroup}
|
|
${textElem.replace('<text ', '<text filter="url(#shadow)" ')}
|
|
</svg>
|
|
`.trim();
|
|
|
|
res.setHeader('Content-Type', 'image/svg+xml');
|
|
res.send(svg);
|
|
} catch (err) {
|
|
console.error(err);
|
|
res.status(500).send('Internal Server Error');
|
|
}
|
|
});
|
|
|
|
app.listen(PORT, () => {
|
|
console.log(`🚀 Badge API running at http://localhost:${PORT}/badge`);
|
|
});
|