/** * PDF Generation Script * Generates well-formatted PDFs from markdown documents */ const puppeteer = require('puppeteer'); const marked = require('marked'); const fs = require('fs').promises; const path = require('path'); const { MongoClient } = require('mongodb'); // MongoDB connection const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/tractatus_dev'; const DB_NAME = process.env.MONGODB_DB || 'tractatus_dev'; // Output directory const OUTPUT_DIR = path.join(__dirname, '../public/downloads'); /** * HTML template for PDF generation */ function generatePdfHtml(document) { return ` ${document.title}

${document.title}

${document.metadata?.version ? `

Version: ${document.metadata.version}

` : ''} ${document.metadata?.date_updated ? `

Last Updated: ${new Date(document.metadata.date_updated).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })}

` : ''}

Document Type: ${document.category || 'Framework Documentation'}

Tractatus AI Safety Framework

https://agenticgovernance.digital

${document.content_html}
`; } /** * Generate PDF for a single document */ async function generatePdf(document, browser) { try { const page = await browser.newPage(); // Generate HTML content const html = generatePdfHtml(document); // Set content await page.setContent(html, { waitUntil: 'networkidle0' }); // Generate filename const filename = `${document.slug}.pdf`; const filepath = path.join(OUTPUT_DIR, filename); // Generate PDF await page.pdf({ path: filepath, format: 'A4', printBackground: true, margin: { top: '2cm', right: '2cm', bottom: '2cm', left: '2cm' }, displayHeaderFooter: true, headerTemplate: '
', footerTemplate: `
/
` }); await page.close(); console.log(` ✓ Generated: ${filename}`); return { success: true, filename }; } catch (error) { console.error(` ✗ Failed to generate PDF for ${document.slug}:`, error.message); return { success: false, error: error.message }; } } /** * Main execution */ async function main() { console.log('=== PDF Generation ===\n'); let client; let browser; try { // Ensure output directory exists await fs.mkdir(OUTPUT_DIR, { recursive: true }); console.log(`Output directory: ${OUTPUT_DIR}\n`); // Connect to MongoDB console.log('Connecting to MongoDB...'); client = await MongoClient.connect(MONGODB_URI); const db = client.db(DB_NAME); console.log('✓ Connected\n'); // Fetch all documents const documents = await db.collection('documents') .find({}) .sort({ title: 1 }) .toArray(); console.log(`Found ${documents.length} published documents\n`); if (documents.length === 0) { console.log('No documents to process'); return; } // Launch Puppeteer console.log('Launching browser...'); browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); console.log('✓ Browser ready\n'); // Generate PDFs const results = []; for (const doc of documents) { console.log(`Processing: ${doc.title}`); const result = await generatePdf(doc, browser); results.push(result); } // Summary console.log('\n=== Generation Complete ===\n'); const successful = results.filter(r => r.success).length; const failed = results.filter(r => !r.success).length; console.log(`✓ Successful: ${successful}`); if (failed > 0) { console.log(`✗ Failed: ${failed}`); } console.log(`\nPDFs saved to: ${OUTPUT_DIR}`); } catch (error) { console.error('\n✗ Error:', error.message); process.exit(1); } finally { if (browser) await browser.close(); if (client) await client.close(); } } // Run if called directly if (require.main === module) { main(); } module.exports = { generatePdf, generatePdfHtml };