Download apps/api/src/services/renderers/pdf-renderer.ts from safetrack/edtech: direct link, hf CLI and curl.
- Browser
- Download file 5.25 kB
-
https://huggingface.co/spaces/safetrack/edtech/resolve/main/apps/api/src/services/renderers/pdf-renderer.ts
- Command line
-
hf download hf://spaces/safetrack/edtech/apps/api/src/services/renderers/pdf-renderer.ts
-
curl -L -o pdf-renderer.ts https://huggingface.co/spaces/safetrack/edtech/resolve/main/apps/api/src/services/renderers/pdf-renderer.ts
5.25 kB
| import puppeteer from 'puppeteer'; | |
| import { OnePagerData } from '@repo/ai-sdk'; | |
| import { DocumentRenderer } from './types'; | |
| export class PdfOnePagerRenderer implements DocumentRenderer<OnePagerData> { | |
| async render(data: OnePagerData): Promise<Buffer> { | |
| // Design System Colors: Primary #1C7C54, Secondary #1B3A57, Accent #F4A261 | |
| 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'], // Required for running as root in Docker/HF | |
| }); | |
| 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; | |
| } | |
| } | |