/** * Generate PDFs for All Public Documents * Creates downloadable PDFs for documents that will be visible on /docs.html * Uses Puppeteer (headless Chrome) for PDF generation */ const { MongoClient } = require('mongodb'); const puppeteer = require('puppeteer'); const fs = require('fs').promises; const path = require('path'); // Correct slugs for public documents (verified from database) const PUBLIC_DOCS = [ // Getting Started (6) 'introduction', 'core-concepts', 'executive-summary-tractatus-inflection-point', 'implementation-guide-v1.1', 'implementation-guide', 'implementation-guide-python-examples', // Research & Theory (7) 'tractatus-framework-research', // Working Paper v0.1 'pluralistic-values-research-foundations', 'the-27027-incident-a-case-study-in-pattern-recognition-bias', 'real-world-ai-governance-a-case-study-in-framework-failure-and-recovery', 'llm-integration-feasibility-research-scope', 'research-topic-concurrent-session-architecture', 'research-topic-rule-proliferation-transactional-overhead', // Technical Reference (5) 'technical-architecture', 'api-reference-complete', 'api-javascript-examples', 'api-python-examples', 'openapi-specification', // Advanced Topics (3) 'value-pluralism-faq', 'tractatus-ai-safety-framework-core-values-and-principles', 'organizational-theory-foundations', // Business Leadership (1) 'business-case-tractatus-framework' ]; function generatePdfHtml(doc) { let contentHtml = ''; if (doc.sections && doc.sections.length > 0) { // Build from sections doc.sections.forEach(section => { contentHtml += `

${section.title}

\n`; if (section.content_html) { contentHtml += section.content_html + '\n'; } }); } else if (doc.content_html) { contentHtml = doc.content_html; } return ` ${doc.title}

${doc.title}

Tractatus AI Safety Framework

${new Date().toISOString().split('T')[0]}

${contentHtml}
`; } async function generatePDF(doc, browser) { try { const outputPdf = path.join(__dirname, `../public/downloads/${doc.slug}.pdf`); // Generate HTML const html = generatePdfHtml(doc); // Create new page const page = await browser.newPage(); // Set content await page.setContent(html, { waitUntil: 'networkidle0' }); // Generate PDF await page.pdf({ path: outputPdf, format: 'A4', printBackground: true, margin: { top: '2cm', right: '2cm', bottom: '2cm', left: '2cm' } }); await page.close(); console.log(` ✓ Generated: ${doc.slug}.pdf`); return { success: true, slug: doc.slug }; } catch (error) { console.error(` ✗ Failed: ${doc.slug} - ${error.message}`); return { success: false, slug: doc.slug, error: error.message }; } } async function run() { const client = new MongoClient('mongodb://localhost:27017'); let browser; try { await client.connect(); const db = client.db('tractatus_dev'); const collection = db.collection('documents'); console.log('═══════════════════════════════════════════════════════════'); console.log(' GENERATING PDFs FOR PUBLIC DOCUMENTS'); console.log('═══════════════════════════════════════════════════════════\n'); console.log(`Total documents: ${PUBLIC_DOCS.length}\n`); // Ensure downloads directory exists const downloadsDir = path.join(__dirname, '../public/downloads'); await fs.mkdir(downloadsDir, { recursive: true }); // Launch browser console.log('Launching browser...\n'); browser = await puppeteer.launch({ headless: 'new', args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const results = { success: [], failed: [], notFound: [] }; for (const slug of PUBLIC_DOCS) { const doc = await collection.findOne({ slug }); if (!doc) { console.log(` ⚠️ Not found: ${slug}`); results.notFound.push(slug); continue; } const result = await generatePDF(doc, browser); if (result.success) { results.success.push(slug); // Update database with PDF path await collection.updateOne( { slug }, { $set: { 'download_formats.pdf': `/downloads/${slug}.pdf`, updated_at: new Date() } } ); } else { results.failed.push({ slug, error: result.error }); } } console.log('\n═══════════════════════════════════════════════════════════'); console.log(' SUMMARY'); console.log('═══════════════════════════════════════════════════════════\n'); console.log(`✅ Successfully generated: ${results.success.length}`); console.log(`✗ Failed: ${results.failed.length}`); console.log(`⚠️ Not found: ${results.notFound.length}\n`); if (results.failed.length > 0) { console.log('Failed PDFs:'); results.failed.forEach(f => console.log(` - ${f.slug}: ${f.error}`)); } if (browser) await browser.close(); await client.close(); process.exit(0); } catch (error) { console.error('Error:', error); if (browser) await browser.close(); await client.close(); process.exit(1); } } run();