freelance-dashboard/convert_to_pdf.py
StillHammer 21ebf32e4f Dashboard avec graphiques, TCD, slicers et checkboxes fonctionnels
- KPIs complets (CA, Heures, Taux, Stats, Objectifs)
- Graphiques CA par client + Heures par client
- TCD Heures x Client x Projet avec Slicer interactif
- Checkboxes dynamiques bien positionnes (E3:E7)
- Documentation technique et guides MCP

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 17:05:25 +07:00

144 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""
Simple Markdown to PDF converter using markdown2 and reportlab
"""
import markdown2
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak, Table, TableStyle
from reportlab.lib import colors
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_JUSTIFY
from html.parser import HTMLParser
import re
class MarkdownToPDFConverter:
def __init__(self, input_file, output_file):
self.input_file = input_file
self.output_file = output_file
self.doc = SimpleDocTemplate(
output_file,
pagesize=A4,
rightMargin=72,
leftMargin=72,
topMargin=72,
bottomMargin=18
)
self.styles = getSampleStyleSheet()
self._setup_styles()
self.story = []
def _setup_styles(self):
"""Setup custom styles"""
# Title style
self.styles.add(ParagraphStyle(
name='CustomTitle',
parent=self.styles['Heading1'],
fontSize=24,
textColor=colors.HexColor('#2C3E50'),
spaceAfter=30,
alignment=TA_CENTER
))
# Heading 2
self.styles.add(ParagraphStyle(
name='CustomHeading2',
parent=self.styles['Heading2'],
fontSize=18,
textColor=colors.HexColor('#2C3E50'),
spaceAfter=12,
spaceBefore=12
))
# Heading 3
self.styles.add(ParagraphStyle(
name='CustomHeading3',
parent=self.styles['Heading3'],
fontSize=14,
textColor=colors.HexColor('#27AE60'),
spaceAfter=10,
spaceBefore=10
))
# Code style
self.styles.add(ParagraphStyle(
name='Code',
parent=self.styles['Normal'],
fontSize=8,
textColor=colors.black,
backColor=colors.HexColor('#ECF0F1'),
leftIndent=20,
rightIndent=20
))
def convert(self):
"""Convert markdown file to PDF"""
# Read markdown file
with open(self.input_file, 'r', encoding='utf-8') as f:
md_content = f.read()
# Convert markdown to HTML
html = markdown2.markdown(md_content, extras=['tables', 'fenced-code-blocks', 'header-ids'])
# Parse HTML and convert to PDF elements
self._parse_html_to_pdf(html)
# Build PDF
self.doc.build(self.story)
def _parse_html_to_pdf(self, html):
"""Parse HTML and convert to PDF elements"""
# Split by major sections
lines = html.split('\n')
for line in lines:
line = line.strip()
if not line:
continue
# Handle headings
if line.startswith('<h1'):
text = re.sub(r'<.*?>', '', line)
self.story.append(Paragraph(text, self.styles['CustomTitle']))
self.story.append(Spacer(1, 0.2*inch))
elif line.startswith('<h2'):
text = re.sub(r'<.*?>', '', line)
self.story.append(Spacer(1, 0.2*inch))
self.story.append(Paragraph(text, self.styles['CustomHeading2']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<h3'):
text = re.sub(r'<.*?>', '', line)
self.story.append(Paragraph(text, self.styles['CustomHeading3']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<p>'):
text = re.sub(r'<.*?>', '', line)
if text:
self.story.append(Paragraph(text, self.styles['Normal']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<code>') or line.startswith('<pre>'):
text = re.sub(r'<.*?>', '', line)
if text:
self.story.append(Paragraph(text, self.styles['Code']))
self.story.append(Spacer(1, 0.1*inch))
elif line.startswith('<li>'):
text = re.sub(r'<.*?>', '', line)
if text:
self.story.append(Paragraph(f"{text}", self.styles['Normal']))
elif line.startswith('<hr'):
self.story.append(Spacer(1, 0.2*inch))
self.story.append(PageBreak())
if __name__ == '__main__':
input_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.md'
output_file = r'C:\Users\alexi\Documents\projects\freelance-dashboard\TECHNICAL_REFERENCE_EN.pdf'
converter = MarkdownToPDFConverter(input_file, output_file)
converter.convert()
print(f"PDF created successfully: {output_file}")