Merged in feature/update-docs (pull request #180)

Update complete pdf code for entire system

* docs

and code for generation of updated docs
This commit is contained in:
Jay Brown
2025-09-09 19:34:03 +00:00
parent 730f3ba11a
commit da6de0080b
15 changed files with 1096 additions and 19 deletions
+153
View File
@@ -0,0 +1,153 @@
#!/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 `![Diagram ${mermaidCounter}](diagram-${mermaidCounter}.png)`;
} 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 `<h${level} id="${id}">${text}</h${level}>`;
}
}
});
// Convert markdown to HTML
const html = marked(content, {
gfm: true,
breaks: false,
headerIds: true,
mangle: false
});
// Create complete HTML document with CSS
const cssContent = fs.readFileSync('/app/docs/custom-styles.css', 'utf8');
const fullHtml = `
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>DoczyAI Documentation</title>
<style>
${cssContent}
body { margin: 0; padding: 20px; }
@page { margin: 2cm; }
</style>
</head>
<body>
${html}
</body>
</html>`;
// Write HTML to temporary file
const htmlFile = `/app/docs/temp-${inputFile.replace('.md', '.html')}`;
fs.writeFileSync(htmlFile, fullHtml);
// Use Chromium to generate PDF with clickable links (suppress stderr)
execSync(`/usr/bin/chromium-browser --headless --disable-gpu --no-sandbox --run-all-compositor-stages-before-draw --virtual-time-budget=10000 --print-to-pdf=/app/docs/${outputFile} --print-to-pdf-no-header file://${htmlFile} 2>/dev/null`);
console.log(`✅ PDF generated: ${outputFile}`);
// Clean up temporary files
try {
fs.unlinkSync(htmlFile);
for (let i = 1; i <= mermaidCounter; i++) {
try {
fs.unlinkSync(`/app/docs/diagram-${i}.mmd`);
// Keep PNG files for debugging, remove in production
// fs.unlinkSync(`/app/docs/diagram-${i}.png`);
} catch (e) {
// Ignore cleanup errors
}
}
} catch (e) {
// Ignore cleanup errors
}
} catch (error) {
console.error('❌ Error converting to PDF:', error.message);
console.error(error.stack);
process.exit(1);
}
}
convertMarkdownToPDF();