| | import puppeteer from 'puppeteer'; |
| | import { OnePagerData } from '../ai/types'; |
| | import { DocumentRenderer } from './types'; |
| |
|
| | export class PdfOnePagerRenderer implements DocumentRenderer<OnePagerData> { |
| | async render(data: OnePagerData): Promise<Buffer> { |
| | |
| | const htmlContent = ` |
| | <!DOCTYPE html> |
| | <html> |
| | <head> |
| | <meta charset="utf-8"> |
| | <style> |
| | @import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@700&family=Inter:wght@400;600&display=swap'); |
| | |
| | body { |
| | font-family: 'Inter', sans-serif; |
| | color: #333; |
| | line-height: 1.6; |
| | margin: 0; |
| | padding: 40px; |
| | background-color: #fff; |
| | } |
| | |
| | header { |
| | text-align: center; |
| | margin-bottom: 30px; |
| | padding-bottom: 20px; |
| | border-bottom: 3px solid #F4A261; |
| | } |
| | |
| | .main-image { |
| | width: 100%; |
| | height: 250px; |
| | object-fit: cover; |
| | border-radius: 8px; |
| | margin-bottom: 20px; |
| | box-shadow: 0 4px 6px rgba(0,0,0,0.1); |
| | } |
| | |
| | h1 { |
| | font-family: 'Montserrat', sans-serif; |
| | color: #1B3A57; |
| | font-size: 28px; |
| | margin: 0 0 10px 0; |
| | text-transform: uppercase; |
| | letter-spacing: 1px; |
| | } |
| | |
| | .tagline { |
| | color: #1C7C54; |
| | font-size: 16px; |
| | font-weight: 600; |
| | margin: 0; |
| | } |
| | |
| | .section { |
| | margin-bottom: 30px; |
| | } |
| | |
| | h2 { |
| | font-family: 'Montserrat', sans-serif; |
| | color: #1B3A57; |
| | font-size: 20px; |
| | border-left: 4px solid #1C7C54; |
| | padding-left: 10px; |
| | margin-bottom: 15px; |
| | } |
| | |
| | p { |
| | font-size: 14px; |
| | margin: 0 0 10px 0; |
| | color: #4a5568; |
| | } |
| | |
| | .cta { |
| | margin-top: 50px; |
| | text-align: center; |
| | background-color: #1B3A57; |
| | color: white; |
| | padding: 20px; |
| | border-radius: 8px; |
| | } |
| | |
| | .cta p { |
| | color: white; |
| | font-size: 16px; |
| | font-weight: 600; |
| | margin: 0; |
| | } |
| | </style> |
| | </head> |
| | <body> |
| | <header> |
| | ${data.mainImage ? `<img src="${data.mainImage}" class="main-image" alt="Brand Visual">` : ''} |
| | <h1>${data.title || '[Nom du Projet]'}</h1> |
| | <p class="tagline">${data.tagline || '[Votre Slogan Stratégique]'}</p> |
| | </header> |
| | |
| | <div class="section"> |
| | <h2>Analyse du Problème</h2> |
| | <p>${data.problem || '[Donnée à compléter]'}</p> |
| | </div> |
| | |
| | <div class="section"> |
| | <h2>Notre Solution Stratégique</h2> |
| | <p>${data.solution || '[Donnée à compléter]'}</p> |
| | </div> |
| | |
| | <div class="section"> |
| | <h2>Cible et Opportunité</h2> |
| | <p>${data.targetAudience || '[Donnée à compléter]'}</p> |
| | </div> |
| | |
| | <div class="section"> |
| | <h2>Modèle Économique & Croissance</h2> |
| | <p>${data.businessModel || '[Donnée à compléter]'}</p> |
| | </div> |
| | ${data.marketSources ? ` |
| | <div class="section" style="margin-top: 40px; border-top: 1px solid #e2e8f0; padding-top: 20px;"> |
| | <p style="font-size: 12px; color: #718096; text-align: center;"><strong>Sources & Données Réelles :</strong> ${data.marketSources}</p> |
| | </div>` : ''} |
| | |
| | <div class="cta"> |
| | <p>${data.callToAction || '[Action Suivante]'}</p> |
| | </div> |
| | </body> |
| | </html> |
| | `; |
| |
|
| | const browser = await puppeteer.launch({ |
| | executablePath: process.env.PUPPETEER_EXECUTABLE_PATH || undefined, |
| | headless: true, |
| | args: ['--no-sandbox', '--disable-setuid-sandbox'], |
| | }); |
| |
|
| | const page = await browser.newPage(); |
| | await page.setContent(htmlContent, { waitUntil: 'networkidle0' }); |
| |
|
| | const pdfBuffer = await page.pdf({ |
| | format: 'A4', |
| | printBackground: true, |
| | margin: { top: '20px', right: '20px', bottom: '20px', left: '20px' } |
| | }); |
| |
|
| | await browser.close(); |
| |
|
| | return pdfBuffer as Buffer; |
| | } |
| | } |
| |
|