#!/usr/bin/env bash # md-to-pdf.sh — Convert a Markdown file to PDF. # # Usage: # md-to-pdf.sh input.md [output.pdf] # # output.pdf defaults to input's basename with a .pdf extension, written # next to input.md. # # Requires: python3 with the 'markdown' and 'weasyprint' packages # sudo pacman -S python-markdown python-weasyprint set -euo pipefail if [[ $# -lt 1 ]]; then echo "Usage: $0 input.md [output.pdf]" >&2 exit 1 fi src="$1" [[ -f "$src" ]] || { echo "md-to-pdf: file not found: $src" >&2; exit 1; } out="${2:-${src%.*}.pdf}" for mod in markdown weasyprint; do python3 -c "import $mod" 2>/dev/null || { echo "md-to-pdf: missing python module '$mod' — install with:" >&2 echo " sudo pacman -S python-markdown python-weasyprint" >&2 exit 1 } done title=$(grep -m1 '^# ' "$src" | sed 's/^# //' || true) [[ -z "$title" ]] && title="$(basename "${src%.*}")" python3 - "$src" "$out" "$title" <<'PYEOF' import sys import markdown from weasyprint import HTML src, out, title = sys.argv[1], sys.argv[2], sys.argv[3] with open(src, encoding="utf-8") as fh: text = fh.read() body_html = markdown.markdown( text, extensions=["tables", "fenced_code", "toc", "def_list"], ) css = """ @page { size: A4; margin: 2cm; } body { font-family: 'DejaVu Sans', sans-serif; font-size: 11pt; line-height: 1.5; color: #1a1a1a; } h1, h2, h3, h4 { font-weight: 700; line-height: 1.25; margin: 1.4em 0 0.5em; } h1 { font-size: 1.9em; border-bottom: 2px solid #333; padding-bottom: 0.2em; } h2 { font-size: 1.4em; border-bottom: 1px solid #999; padding-bottom: 0.15em; } h3 { font-size: 1.15em; } p, li { margin: 0.4em 0; } code, pre { font-family: 'DejaVu Sans Mono', monospace; font-size: 0.85em; background: #f2f2f2; border-radius: 3px; } code { padding: 0.1em 0.35em; } pre { padding: 0.8em 1em; overflow-x: auto; white-space: pre-wrap; } pre code { padding: 0; background: none; } table { width: 100%; border-collapse: collapse; margin: 1em 0; font-size: 0.85em; } th, td { border: 1px solid #999; padding: 0.4em 0.6em; text-align: left; vertical-align: top; } th { background: #e5e5e5; } tr:nth-child(even) td { background: #fafafa; } blockquote { border-left: 4px solid #999; margin: 1em 0; padding: 0.3em 1em; color: #444; } a { color: #1a4fa0; } """ html = f"{title}" \ f"{body_html}" HTML(string=html, base_url=src).write_pdf(out) print(f"Wrote {out}") PYEOF