md-pdf-mcp

by seanivore
Verified
  • md_pdf_mcp
"""VS Code Markdown Style Implementation for ReportLab PLATYPUS This module provides an exact implementation of VS Code's markdown styling for ReportLab's PLATYPUS (Page Layout and Typography Using Scripts) system. """ from reportlab.lib import colors from reportlab.lib.styles import StyleSheet1, ParagraphStyle from reportlab.lib.units import inch from reportlab.lib.enums import TA_LEFT, TA_CENTER from reportlab.lib.colors import Color, HexColor from reportlab.pdfbase import pdfmetrics from reportlab.pdfbase.ttfonts import TTFont # Register fonts in document hierarchy order # H1 - Title pdfmetrics.registerFont(TTFont('BerninaSans-CompressedBold', 'fonts/TTF/Bernina Sans-Compressed Bold.ttf')) # H2 - Role/Bold Text pdfmetrics.registerFont(TTFont('BerninoSans-CondensedBold', 'fonts/TTF/Bernino Sans-Condensed Bold.ttf')) # H3 - Date/Italics pdfmetrics.registerFont(TTFont('BerninoSans-Light', 'fonts/TTF/Bernino Sans-Light.ttf')) pdfmetrics.registerFont(TTFont('BerninoSans-LightItalic', 'fonts/TTF/Bernino Sans-Light Italic.ttf')) # H4 - Section Headers pdfmetrics.registerFont(TTFont('BerninaSans-CondensedBold', 'fonts/TTF/Bernina Sans-Condensed Bold.ttf')) # H5 - Subsection Titles pdfmetrics.registerFont(TTFont('BerninaSans-Narrow', 'fonts/TTF/Bernina Sans-Narrow Regular.ttf')) # Body Text pdfmetrics.registerFont(TTFont('BerninoSans', 'fonts/TTF/Bernino Sans-Regular.ttf')) # Core font variations we need pdfmetrics.registerFont(TTFont('BerninoSans-Bold', 'fonts/TTF/Bernino Sans-Bold.ttf')) pdfmetrics.registerFont(TTFont('BerninoSans-NarrowExtrabold', 'fonts/TTF/Bernina Sans-Narrow Extrabold.ttf')) def px_to_pt(px: float) -> float: """Convert pixels to points (1px = 0.75pt)""" return px * 0.75 def em_to_pt(em: float, base_size: float = 14) -> float: """Convert em to points based on base font size""" return em * base_size # VS Code's exact colors THEME_COLORS = { 'light': { 'text': colors.black, 'background': colors.white, 'link': HexColor('#0090f1'), 'pre_background': Color(30/255, 30/255, 30/255, alpha=0.95), 'pre_text': Color(220/255, 220/255, 220/255), 'comment': Color(87/255, 166/255, 74/255), 'widget_border': Color(0, 0, 0, alpha=0.14), # Needed for code blocks }, 'high-contrast': { 'text': colors.black, 'background': colors.white, 'link': HexColor('#0090f1'), 'pre_background': colors.black, 'pre_text': colors.white, 'comment': Color(87/255, 166/255, 74/255), 'widget_border': colors.black, # Needed for code blocks } } def get_vscode_stylesheet(theme: str = 'light') -> StyleSheet1: """Generate a ReportLab StyleSheet matching VS Code's markdown styling.""" styles = StyleSheet1() colors = THEME_COLORS[theme] # Base style for normal document flow styles.add(ParagraphStyle( name='Body', fontName='BerninoSans', fontSize=px_to_pt(11), leading=em_to_pt(1.2), textColor=colors['text'], backColor=colors['background'], alignment=TA_LEFT, spaceAfter=em_to_pt(1.0), firstLineIndent=0, leftIndent=0, rightIndent=0, bulletIndent=em_to_pt(0.5), )) # Regular heading styles - all left aligned styles.add(ParagraphStyle( name='Heading1', parent=styles['Body'], fontName='BerninaSans-CompressedBold', fontSize=px_to_pt(48), leading=em_to_pt(3.0), spaceBefore=em_to_pt(0.2), spaceAfter=0, )) # H2 - Role/Bold Text styles.add(ParagraphStyle( name='Heading2', parent=styles['Body'], fontName='BerninoSans-CondensedBold', fontSize=px_to_pt(16), leading=em_to_pt(1.15), spaceBefore=em_to_pt(0.2), spaceAfter=em_to_pt(2.0), )) # H3 - Date/Italics styles.add(ParagraphStyle( name='Heading3', parent=styles['Body'], fontName='BerninoSans-LightItalic', fontSize=px_to_pt(14), leading=em_to_pt(1.2), spaceBefore=0, spaceAfter=em_to_pt(3.0), )) # H4 - Section Headers styles.add(ParagraphStyle( name='Heading4', parent=styles['Body'], fontName='BerninaSans-CondensedBold', fontSize=px_to_pt(18), leading=em_to_pt(1.2), spaceBefore=em_to_pt(1.5), spaceAfter=em_to_pt(1.0), )) # H5 - Now a regular heading styles.add(ParagraphStyle( name='Heading5', parent=styles['Body'], fontName='BerninaSans-Narrow', fontSize=px_to_pt(14), # Smaller than H4 leading=em_to_pt(1.2), spaceBefore=em_to_pt(1.0), spaceAfter=em_to_pt(0.5), )) # List items styles.add(ParagraphStyle( name='ListItem', parent=styles['Body'], fontName='BerninoSans-NarrowExtrabold', fontSize=px_to_pt(11), leftIndent=em_to_pt(1.2), bulletIndent=em_to_pt(0.8), spaceBefore=em_to_pt(0.2), spaceAfter=em_to_pt(0.2), leading=13, wordSpacing=2, tracking=110, textTransform='uppercase', )) # Emphasized text (italics) styles.add(ParagraphStyle( name='Emphasis', parent=styles['Body'], fontName='BerninoSans-LightItalic', textColor=colors['text'], )) # Strong text (bold) styles.add(ParagraphStyle( name='Strong', parent=styles['Body'], fontName='BerninoSans-Bold', textColor=colors['text'], )) # Code blocks styles.add(ParagraphStyle( name='Code', parent=styles['Body'], fontName='Courier', fontSize=px_to_pt(11), leading=em_to_pt(1.2), textColor=colors['pre_text'], )) styles.add(ParagraphStyle( name='CodeComment', parent=styles['Code'], textColor=colors['comment'], )) styles.add(ParagraphStyle( name='Pre', parent=styles['Code'], backColor=colors['pre_background'], borderPadding=px_to_pt(12), leftIndent=px_to_pt(12), rightIndent=px_to_pt(12), spaceBefore=px_to_pt(6), spaceAfter=px_to_pt(6), borderWidth=1, borderColor=colors['widget_border'], # Used for code block border borderRadius=3, textColor=colors['pre_text'], )) # Links styles.add(ParagraphStyle( name='Link', parent=styles['Body'], textColor=colors['link'], underline=1, )) # Signature style - preserve line breaks styles.add(ParagraphStyle( name='Signature', parent=styles['Body'], spaceBefore=em_to_pt(1.0), spaceAfter=em_to_pt(0.5), keepWithNext=True, )) return styles