Skip to content

Commit 38ee36d

Browse files
committed
fix: Implement proper Gotenberg markdown conversion according to official docs
🔧 Gotenberg API Compliance: - Follow official Gotenberg markdown conversion pattern from docs - Create HTML wrapper file (index.html) with toHTML template function - Send both index.html and .md file as separate files to Gotenberg - Add proper CSS styling for professional PDF appearance 📚 Based on Gotenberg Documentation: - /forms/chromium/convert/markdown requires index.html + *.md files - HTML wrapper uses {{ toHTML "filename.md" }} template function - Replaced \pagebreak with CSS page-break-before: always 🛠️ Implementation Details: - Generate HTML wrapper with embedded CSS for styling - Send files as multipart form with correct content types - Proper cleanup of both temporary files - Enhanced error handling for both file types ✅ Expected Result: - Proper PDF generation from markdown reports - Professional styling with fonts, tables, and page breaks - Resolves Gotenberg 400 'form file index.html is required' error
1 parent 45f992c commit 38ee36d

File tree

2 files changed

+41
-6
lines changed

2 files changed

+41
-6
lines changed

main.py

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -542,11 +542,39 @@ async def _generate_lint_pdf_report(lint_result: LintResult, document_name: str,
542542
# Ensure temp directory exists
543543
os.makedirs('temp', exist_ok=True)
544544

545-
# Create temporary markdown file
545+
# Create temporary markdown file and HTML wrapper for Gotenberg
546546
import tempfile
547+
548+
# Create markdown file
547549
with tempfile.NamedTemporaryFile(mode='w', suffix='.md', delete=False, dir='temp') as md_file:
548550
md_file.write(markdown_content)
549551
md_file_path = md_file.name
552+
md_filename = os.path.basename(md_file_path)
553+
554+
# Create HTML wrapper file for Gotenberg markdown conversion
555+
html_wrapper = f'''<!doctype html>
556+
<html lang="en">
557+
<head>
558+
<meta charset="utf-8">
559+
<title>DocX Template Linting Report</title>
560+
<style>
561+
body {{ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; margin: 40px; }}
562+
table {{ border-collapse: collapse; width: 100%; margin: 20px 0; }}
563+
th, td {{ border: 1px solid #ddd; padding: 12px; text-align: left; }}
564+
th {{ background-color: #f5f5f5; }}
565+
code {{ background-color: #f5f5f5; padding: 2px 4px; border-radius: 3px; }}
566+
pre {{ background-color: #f5f5f5; padding: 15px; border-radius: 5px; overflow-x: auto; }}
567+
.page-break {{ page-break-before: always; }}
568+
</style>
569+
</head>
570+
<body>
571+
{{{{ toHTML "{md_filename}" }}}}
572+
</body>
573+
</html>'''
574+
575+
with tempfile.NamedTemporaryFile(mode='w', suffix='.html', delete=False, dir='temp') as html_file:
576+
html_file.write(html_wrapper)
577+
html_file_path = html_file.name
550578

551579
# Generate PDF filename
552580
base_name = os.path.splitext(document_name)[0]
@@ -567,8 +595,12 @@ async def _generate_lint_pdf_report(lint_result: LintResult, document_name: str,
567595
logger.info(f"Converting lint report to PDF via Gotenberg: {resource_url}")
568596
logger.debug(f"Markdown content length: {len(markdown_content)} characters")
569597

570-
with open(md_file_path, 'rb') as md_file:
571-
files = {'files': ('index.html', md_file, 'text/markdown')}
598+
# Send both HTML wrapper and markdown file to Gotenberg
599+
with open(html_file_path, 'rb') as html_file, open(md_file_path, 'rb') as md_file:
600+
files = [
601+
('files', ('index.html', html_file, 'text/html')),
602+
('files', (md_filename, md_file, 'text/markdown'))
603+
]
572604

573605
# Make request to Gotenberg with timeout
574606
response = requests.post(
@@ -619,9 +651,10 @@ async def _generate_lint_pdf_report(lint_result: LintResult, document_name: str,
619651

620652
logger.info(f"Lint report PDF generated successfully: {pdf_file_path} ({len(response.content)} bytes)")
621653

622-
# Clean up markdown file
654+
# Clean up temporary files
623655
try:
624656
os.unlink(md_file_path)
657+
os.unlink(html_file_path)
625658
except:
626659
pass
627660

@@ -637,6 +670,8 @@ async def _generate_lint_pdf_report(lint_result: LintResult, document_name: str,
637670
try:
638671
if 'md_file_path' in locals() and os.path.exists(md_file_path):
639672
os.unlink(md_file_path)
673+
if 'html_file_path' in locals() and os.path.exists(html_file_path):
674+
os.unlink(html_file_path)
640675
if 'pdf_file_path' in locals() and os.path.exists(pdf_file_path):
641676
os.unlink(pdf_file_path)
642677
except:

services/markdown_formatter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def format_lint_report(
4747
markdown_parts.append(self._create_summary(lint_result))
4848

4949
# New page for detailed results
50-
markdown_parts.append("\n\\pagebreak\n")
50+
markdown_parts.append('\n<div class="page-break"></div>\n')
5151

5252
# Detailed results section
5353
if lint_result.errors or lint_result.warnings:
@@ -57,7 +57,7 @@ def format_lint_report(
5757

5858
# Template preview if available
5959
if lint_result.template_preview:
60-
markdown_parts.append("\n\\pagebreak\n")
60+
markdown_parts.append('\n<div class="page-break"></div>\n')
6161
markdown_parts.append(self._create_template_preview(lint_result.template_preview))
6262

6363
return "\n".join(markdown_parts)

0 commit comments

Comments
 (0)