112 lines
4.1 KiB
Python
112 lines
4.1 KiB
Python
#!/usr/bin/env python3
|
|
"""Convert a Markdown file into a Cloud Drift branded .docx and/or .pdf.
|
|
|
|
Usage:
|
|
python3 convert.py INPUT.md [--format docx|pdf|both] [--output PATH]
|
|
[--reference-doc PATH]
|
|
|
|
docx is produced by pandoc using the bundled Cloud Drift reference.docx
|
|
(fonts, colors, logo header, footer pagination). pdf is produced by asking
|
|
macOS Pages to open that docx and export it to PDF, so the PDF is pixel-for-
|
|
pixel the same branded layout, not a second independent template.
|
|
"""
|
|
import argparse
|
|
import shutil
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
SKILL_DIR = Path(__file__).resolve().parent.parent
|
|
REFERENCE_DOC = SKILL_DIR / "assets" / "clouddrift-reference.docx"
|
|
|
|
|
|
def convert_to_docx(input_md: Path, output_docx: Path, reference_doc: Path):
|
|
if shutil.which("pandoc") is None:
|
|
sys.exit("pandoc is not installed or not on PATH.")
|
|
cmd = [
|
|
"pandoc",
|
|
str(input_md),
|
|
"-o",
|
|
str(output_docx),
|
|
f"--reference-doc={reference_doc}",
|
|
"--standalone",
|
|
]
|
|
subprocess.run(cmd, check=True)
|
|
print(f"Wrote {output_docx}")
|
|
|
|
|
|
def convert_docx_to_pdf(input_docx: Path, output_pdf: Path):
|
|
"""Use macOS Pages (via AppleScript) to export the docx to PDF, preserving
|
|
the exact branded layout produced by the reference.docx styles."""
|
|
if sys.platform != "darwin":
|
|
sys.exit("PDF export currently requires macOS (uses Pages via AppleScript).")
|
|
script = f'''
|
|
try
|
|
tell application "Pages"
|
|
set theDoc to open POSIX file "{input_docx.resolve()}"
|
|
delay 2
|
|
export theDoc to POSIX file "{output_pdf.resolve()}" as PDF
|
|
close theDoc saving no
|
|
end tell
|
|
return "SUCCESS"
|
|
on error errMsg number errNum
|
|
return "ERROR: " & errMsg & " (" & errNum & ")"
|
|
end try
|
|
'''
|
|
result = subprocess.run(["osascript", "-e", script], capture_output=True, text=True)
|
|
out = result.stdout.strip()
|
|
if out != "SUCCESS":
|
|
sys.exit(
|
|
"Pages PDF export failed: "
|
|
f"{out or result.stderr.strip()}\n"
|
|
"If this is the first run, macOS may need you to grant automation "
|
|
"permission for controlling Pages (System Settings > Privacy & "
|
|
"Security > Automation), or Pages may need a moment after "
|
|
"launching — try again."
|
|
)
|
|
print(f"Wrote {output_pdf}")
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument("input", type=Path, help="Input Markdown file")
|
|
parser.add_argument(
|
|
"--format", choices=["docx", "pdf", "both"], default="docx",
|
|
help="Output format (default: docx)",
|
|
)
|
|
parser.add_argument(
|
|
"--output", type=Path, default=None,
|
|
help="Output path (without extension needed for --format both). "
|
|
"Defaults to the input filename next to the input file.",
|
|
)
|
|
parser.add_argument(
|
|
"--reference-doc", type=Path, default=REFERENCE_DOC,
|
|
help="Override the Cloud Drift reference.docx template",
|
|
)
|
|
args = parser.parse_args()
|
|
|
|
if not args.input.exists():
|
|
sys.exit(f"Input file not found: {args.input}")
|
|
if not args.reference_doc.exists():
|
|
sys.exit(f"Reference doc not found: {args.reference_doc}")
|
|
|
|
stem = args.output if args.output else args.input.with_suffix("")
|
|
docx_path = stem.with_suffix(".docx")
|
|
pdf_path = stem.with_suffix(".pdf")
|
|
|
|
if args.format in ("docx", "both"):
|
|
convert_to_docx(args.input, docx_path, args.reference_doc)
|
|
|
|
if args.format in ("pdf", "both"):
|
|
if not docx_path.exists():
|
|
convert_to_docx(args.input, docx_path, args.reference_doc)
|
|
convert_docx_to_pdf(docx_path, pdf_path)
|
|
if args.format == "pdf" and docx_path.exists() and args.output is None:
|
|
# pdf-only was requested and we only made the docx as an
|
|
# intermediate step; clean it up unless the caller named an
|
|
# explicit --output (in which case leave both, they may want it).
|
|
docx_path.unlink()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|