| | import sys
|
| | import time
|
| | import os
|
| | import logging
|
| | from watchdog.observers import Observer
|
| | from watchdog.events import FileSystemEventHandler
|
| | import markdown
|
| | from xhtml2pdf import pisa
|
| | import threading
|
| |
|
| |
|
| | INPUT_DIR = os.path.abspath("input")
|
| | OUTPUT_DIR = os.path.abspath("output")
|
| |
|
| |
|
| | os.makedirs(INPUT_DIR, exist_ok=True)
|
| | os.makedirs(OUTPUT_DIR, exist_ok=True)
|
| |
|
| | logging.basicConfig(level=logging.INFO,
|
| | format='%(asctime)s - %(message)s',
|
| | datefmt='%Y-%m-%d %H:%M:%S')
|
| |
|
| | def convert_md_to_pdf(input_path):
|
| | """Reads a markdown file and converts it to PDF."""
|
| | try:
|
| | filename = os.path.basename(input_path)
|
| | name, _ = os.path.splitext(filename)
|
| | output_path = os.path.join(OUTPUT_DIR, f"{name}.pdf")
|
| |
|
| | logging.info(f"Processing: {filename}")
|
| |
|
| |
|
| | with open(input_path, 'r', encoding='utf-8') as f:
|
| | md_content = f.read()
|
| |
|
| |
|
| |
|
| |
|
| | html_content = markdown.markdown(md_content, extensions=['tables', 'fenced_code'])
|
| |
|
| |
|
| |
|
| | full_html = f"""
|
| | <html>
|
| | <head>
|
| | <style>
|
| | @page {{
|
| | size: A4;
|
| | margin: 2cm;
|
| | }}
|
| | body {{
|
| | font-family: Helvetica, sans-serif;
|
| | font-size: 12pt;
|
| | }}
|
| | table {{
|
| | border: 1px solid black;
|
| | border-collapse: collapse;
|
| | width: 100%;
|
| | margin-bottom: 1em;
|
| | }}
|
| | th, td {{
|
| | border: 1px solid black;
|
| | padding: 5px;
|
| | text-align: left;
|
| | }}
|
| | th {{
|
| | background-color: #f2f2f2;
|
| | font-weight: bold;
|
| | }}
|
| | code {{
|
| | font-family: Courier;
|
| | background-color: #f5f5f5;
|
| | }}
|
| | pre {{
|
| | background-color: #f5f5f5;
|
| | padding: 10px;
|
| | border: 1px solid #ccc;
|
| | }}
|
| | </style>
|
| | </head>
|
| | <body>
|
| | {html_content}
|
| | </body>
|
| | </html>
|
| | """
|
| |
|
| |
|
| | with open(output_path, "wb") as pdf_file:
|
| | pisa_status = pisa.CreatePDF(
|
| | full_html,
|
| | dest=pdf_file
|
| | )
|
| |
|
| | if pisa_status.err:
|
| | logging.error(f"Error converting {filename}: {pisa_status.err}")
|
| | else:
|
| | logging.info(f"Successfully created: {output_path}")
|
| |
|
| | except Exception as e:
|
| | logging.error(f"Failed to convert {input_path}: {e}")
|
| |
|
| | class MDHandler(FileSystemEventHandler):
|
| | def on_created(self, event):
|
| | if not event.is_directory and event.src_path.lower().endswith('.md'):
|
| |
|
| |
|
| | time.sleep(0.5)
|
| | convert_md_to_pdf(event.src_path)
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| |
|
| | def on_moved(self, event):
|
| | if not event.is_directory and event.dest_path.lower().endswith('.md'):
|
| | time.sleep(0.5)
|
| | convert_md_to_pdf(event.dest_path)
|
| |
|
| | if __name__ == "__main__":
|
| | logging.info("Starting Watchdog for MD -> PDF conversion...")
|
| | logging.info(f"Monitoring: {INPUT_DIR}")
|
| | logging.info(f"Output to: {OUTPUT_DIR}")
|
| |
|
| | event_handler = MDHandler()
|
| | observer = Observer()
|
| | observer.schedule(event_handler, INPUT_DIR, recursive=False)
|
| | observer.start()
|
| |
|
| | try:
|
| | while True:
|
| | time.sleep(1)
|
| | except KeyboardInterrupt:
|
| | observer.stop()
|
| | observer.join()
|
| |
|