| import sharp from 'sharp'; |
| import path from 'path'; |
|
|
| |
| |
| |
| function wrapText(text: string, maxCharsPerLine: number): string[] { |
| const words = text.split(' '); |
| const lines: string[] = []; |
| let currentLine = ''; |
|
|
| words.forEach(word => { |
| if ((currentLine + word).length > maxCharsPerLine) { |
| lines.push(currentLine.trim()); |
| currentLine = word + ' '; |
| } else { |
| currentLine += word + ' '; |
| } |
| }); |
| lines.push(currentLine.trim()); |
| return lines; |
| } |
|
|
| |
| |
| |
| export async function generatePitchCard(text: string): Promise<Buffer> { |
| const templatePath = path.resolve(__dirname, '../assets/templates/pitch_card.png'); |
|
|
| const lines = wrapText(text.toUpperCase(), 25); |
| const lineHeight = 60; |
| const startY = 540 - (lines.length * lineHeight) / 2; |
|
|
| const svgText = lines.map((line, i) => |
| `<text x="540" y="${startY + (i * lineHeight)}" class="text">${line}</text>` |
| ).join(''); |
|
|
| const svgOverlay = Buffer.from(` |
| <svg width="1080" height="1080"> |
| <style> |
| .title { |
| fill: #d4af37; |
| font-size: 56px; |
| font-family: sans-serif; |
| font-weight: 900; |
| text-anchor: middle; |
| text-transform: uppercase; |
| letter-spacing: 3px; |
| } |
| .label { |
| fill: #ffffff; |
| font-size: 28px; |
| font-family: sans-serif; |
| font-weight: 600; |
| text-anchor: middle; |
| opacity: 0.8; |
| } |
| .text { |
| fill: #ffffff; |
| font-size: 48px; |
| font-family: sans-serif; |
| font-weight: 800; |
| text-anchor: middle; |
| letter-spacing: 1px; |
| } |
| </style> |
| <text x="540" y="250" class="title">MA CARTE BUSINESS</text> |
| <text x="540" y="440" class="label">MON PROJET :</text> |
| ${svgText} |
| <text x="540" y="850" class="label">XAMLÉ - 2026</text> |
| </svg>`); |
|
|
| return sharp(templatePath) |
| .composite([{ input: svgOverlay, top: 0, left: 0 }]) |
| .png() |
| .toBuffer(); |
| } |
|
|