telegram-badge
Version:
Generate Telegram group member count badges for GitHub README
122 lines (121 loc) • 7.85 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateBadgeSVG = generateBadgeSVG;
// Telegram logo as base64 encoded SVG
const TELEGRAM_LOGO = `<svg xmlns="http://www.w3.org/2000/svg" fill="white" viewBox="0 0 24 24" width="14" height="14">
<path d="M12 0C5.373 0 0 5.373 0 12s5.373 12 12 12 12-5.373 12-12S18.627 0 12 0zm5.894 8.221l-1.97 9.28c-.145.658-.537.818-1.084.508l-3-2.21-1.446 1.394c-.14.18-.357.295-.6.295-.002 0-.003 0-.005 0l.213-3.054 5.56-5.022c.24-.213-.054-.334-.373-.121l-6.869 4.326-2.96-.924c-.64-.203-.658-.64.135-.954l11.566-4.458c.538-.196 1.006.128.832.941z"/>
</svg>`;
function generateBadgeSVG(format) {
const { label, message, color, labelColor, style, logo } = format;
const logoSpace = logo ? 20 : 0;
// Better text width calculation with more spacing
// Always add logoSpace to width calculation
const labelWidth = label.length * 7 + 10 + logoSpace;
const messageWidth = message.length * 7 + 20;
const totalWidth = labelWidth + messageWidth;
// Create logo element
const logoElement = logo ? `<image x="5" y="3" width="14" height="14" href="data:image/svg+xml;base64,${btoa(TELEGRAM_LOGO)}"/>` : '';
// For-the-badge style
if (style === 'for-the-badge') {
const logoForBadge = logo ? `<image x="5" y="7" width="14" height="14" href="data:image/svg+xml;base64,${btoa(TELEGRAM_LOGO)}"/>` : '';
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${totalWidth}" height="28" role="img" aria-label="${label}: ${message}">
<title>${label}: ${message}</title>
<g shape-rendering="crispEdges">
<rect width="${labelWidth}" height="28" fill="${labelColor}"/>
<rect x="${labelWidth}" width="${messageWidth}" height="28" fill="${color}"/>
</g>
${logoForBadge}
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="100">
<text x="${(labelWidth / 2 + (logo ? 7 : 0)) * 10}" y="175" transform="scale(.1)" fill="#fff" letter-spacing="1">${label.toUpperCase()}</text>
<text x="${(labelWidth + messageWidth / 2) * 10}" y="175" font-weight="bold" transform="scale(.1)" fill="#fff" letter-spacing="1">${message.toUpperCase()}</text>
</g>
</svg>`;
}
// Flat-square style
if (style === 'flat-square') {
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${totalWidth}" height="20" role="img" aria-label="${label}: ${message}">
<title>${label}: ${message}</title>
<g shape-rendering="crispEdges">
<rect width="${labelWidth}" height="20" fill="${labelColor}"/>
<rect x="${labelWidth}" width="${messageWidth}" height="20" fill="${color}"/>
</g>
${logoElement}
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
<text x="${(labelWidth / 2 + (logo ? 7 : 0)) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.8">${label}</text>
<text x="${(labelWidth + messageWidth / 2) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.8">${message}</text>
</g>
</svg>`;
}
// Social style
if (style === 'social') {
const socialLogoElement = logo ? `<image x="7" y="3" width="14" height="14" href="data:image/svg+xml;base64,${btoa(TELEGRAM_LOGO)}"/>` : '';
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${totalWidth + 4}" height="20" style="border-radius: 3px" role="img" aria-label="${label}: ${message}">
<title>${label}: ${message}</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="r">
<rect width="${totalWidth + 4}" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#r)">
<rect width="${labelWidth + 2}" height="20" fill="${labelColor}"/>
<rect x="${labelWidth + 2}" width="${messageWidth + 2}" height="20" fill="${color}"/>
<rect width="${totalWidth + 4}" height="20" fill="url(#s)"/>
</g>
${socialLogoElement}
<g fill="#333" text-anchor="middle" font-family="Helvetica,Arial,sans-serif" font-weight="700" font-size="110">
<text x="${(labelWidth / 2 + 1 + (logo ? 7 : 0)) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.6">${label}</text>
<text x="${(labelWidth + messageWidth / 2 + 2) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.6">${message}</text>
</g>
</svg>`;
}
// Plastic style
if (style === 'plastic') {
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${totalWidth}" height="20" role="img" aria-label="${label}: ${message}">
<title>${label}: ${message}</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#fff" stop-opacity=".7"/>
<stop offset=".1" stop-color="#aaa" stop-opacity=".1"/>
<stop offset=".9" stop-color="#000" stop-opacity=".3"/>
<stop offset="1" stop-color="#000" stop-opacity=".5"/>
</linearGradient>
<clipPath id="r">
<rect width="${totalWidth}" height="20" rx="4" fill="#fff"/>
</clipPath>
<g clip-path="url(#r)">
<rect width="${labelWidth}" height="20" fill="${labelColor}"/>
<rect x="${labelWidth}" width="${messageWidth}" height="20" fill="${color}"/>
<rect width="${totalWidth}" height="20" fill="url(#s)"/>
</g>
${logoElement}
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
<text x="${(labelWidth / 2 + (logo ? 7 : 0)) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.8">${label}</text>
<text x="${(labelWidth + messageWidth / 2) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.8">${message}</text>
</g>
</svg>`;
}
// Default flat style
return `<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="${totalWidth}" height="20" role="img" aria-label="${label}: ${message}">
<title>${label}: ${message}</title>
<linearGradient id="s" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<clipPath id="r">
<rect width="${totalWidth}" height="20" rx="3" fill="#fff"/>
</clipPath>
<g clip-path="url(#r)">
<rect width="${labelWidth}" height="20" fill="${labelColor}"/>
<rect x="${labelWidth}" width="${messageWidth}" height="20" fill="${color}"/>
<rect width="${totalWidth}" height="20" fill="url(#s)"/>
</g>
${logoElement}
<g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110">
<text aria-hidden="true" x="${(labelWidth / 2 + (logo ? 7 : 0)) * 10}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" letter-spacing="0.8">${label}</text>
<text x="${(labelWidth / 2 + (logo ? 7 : 0)) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.8">${label}</text>
<text aria-hidden="true" x="${(labelWidth + messageWidth / 2) * 10}" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" letter-spacing="0.8">${message}</text>
<text x="${(labelWidth + messageWidth / 2) * 10}" y="140" transform="scale(.1)" fill="#fff" letter-spacing="0.8">${message}</text>
</g>
</svg>`;
}