#!/usr/bin/env node /** * Generate PDF from Single Markdown File * * Usage: node scripts/generate-single-pdf.js [output.pdf] * * Copyright 2025 Tractatus Project * Licensed under Apache License 2.0 */ const puppeteer = require('puppeteer'); const marked = require('marked'); const fs = require('fs').promises; const path = require('path'); // Parse command line arguments const args = process.argv.slice(2); if (args.length < 1) { console.error('Usage: node scripts/generate-single-pdf.js [output.pdf]'); process.exit(1); } const inputPath = path.resolve(args[0]); const outputPath = args[1] ? path.resolve(args[1]) : inputPath.replace(/\.md$/, '.pdf'); /** * HTML template for PDF generation */ function generatePdfHtml(title, content) { return ` ${title}

${title}

${content}
`; } /** * Main execution */ async function main() { console.log('=== PDF Generation from Markdown ===\n'); let browser; try { // Read markdown file console.log(`Reading: ${inputPath}`); const markdown = await fs.readFile(inputPath, 'utf8'); // Extract title from first # heading const titleMatch = markdown.match(/^#\s+(.+)$/m); const title = titleMatch ? titleMatch[1] : path.basename(inputPath, '.md'); console.log(`Title: ${title}`); // Convert markdown to HTML console.log('Converting markdown to HTML...'); const contentHtml = marked.parse(markdown); // Generate full HTML const html = generatePdfHtml(title, contentHtml); // Launch Puppeteer console.log('Launching browser...'); browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox', '--disable-setuid-sandbox'] }); const page = await browser.newPage(); // Set content console.log('Rendering HTML...'); await page.setContent(html, { waitUntil: 'networkidle0' }); // Generate PDF console.log(`Generating PDF: ${outputPath}`); await page.pdf({ path: outputPath, format: 'A4', printBackground: true, margin: { top: '2cm', right: '2cm', bottom: '2cm', left: '2cm' }, displayHeaderFooter: true, headerTemplate: '
', footerTemplate: `
/
` }); console.log('\n✓ PDF generated successfully!\n'); console.log(`Output: ${outputPath}`); } catch (error) { console.error('\n✗ Error:', error.message); process.exit(1); } finally { if (browser) await browser.close(); } } // Run main();