#!/usr/bin/env node
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');
const { marked } = require('marked');
// Custom script to handle Mermaid rendering and fix internal links
async function convertMarkdownToPDF() {
const inputFile = process.argv[2] || 'complete-documentation.md';
const outputFile = inputFile.replace('.md', '.pdf');
console.log(`Converting ${inputFile} to PDF with Mermaid support...`);
try {
// Read the markdown file
let content = fs.readFileSync(`/app/docs/${inputFile}`, 'utf8');
// Remove YAML front matter if present
content = content.replace(/^---\n[\s\S]*?\n---\n/, '');
// Remove emojis that don't render well in PDF
content = content.replace(/📋|🛠️|🔧|📊|🏗️|🎉|✅|❌|🚀|📝|📚|🔍|⚠️|💡/g, '');
// Helper function to generate section ID from text
function generateSectionId(text) {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, '') // Remove special chars
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/-+/g, '-') // Collapse multiple hyphens
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
}
// Fix internal links to work within the same document
// Convert [text](filename.md) to [text](#section-name)
let linkCount = 0;
content = content.replace(/\[([^\]]+)\]\((\d+-[^)]+\.md)\)/g, (match, linkText, filename) => {
// Use the link text to generate the section ID (since that's what the header will be)
const sectionId = generateSectionId(linkText);
linkCount++;
return `[${linkText}](#${sectionId})`;
});
// Fix relative links ./filename.md
content = content.replace(/\[([^\]]+)\]\(\.\/(\d+-[^)]+\.md)\)/g, (match, linkText, filename) => {
const sectionId = generateSectionId(linkText);
linkCount++;
return `[${linkText}](#${sectionId})`;
});
console.log(`✅ Processed ${linkCount} internal links`);
// Process Mermaid diagrams
let mermaidCounter = 0;
content = content.replace(/```mermaid\n([\s\S]*?)\n```/g, (match, mermaidCode) => {
mermaidCounter++;
const diagramFile = `/app/docs/diagram-${mermaidCounter}.mmd`;
const imageFile = `/app/docs/diagram-${mermaidCounter}.png`;
// Write mermaid code to temporary file
fs.writeFileSync(diagramFile, mermaidCode.trim());
try {
// Generate PNG from mermaid
execSync(`mmdc -i ${diagramFile} -o ${imageFile} -w 800 -H 600 --backgroundColor white`);
// Replace with image reference
return ``;
} catch (error) {
console.warn(`Warning: Failed to render Mermaid diagram ${mermaidCounter}:`, error.message);
// Return original code block if mermaid fails
return match;
}
});
// Configure marked to generate proper IDs for headers
marked.use({
renderer: {
heading(text, level) {
// Generate ID from text content
const id = text
.toLowerCase()
.replace(/[^\w\s-]/g, '') // Remove special chars
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/-+/g, '-') // Collapse multiple hyphens
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
return `