PythonとPandocで複数のMarkdown(md)をPDFにまとめる

最近、ブログの下書きをObsidian&Markdownで書くようにした関係で、そこから発展して生活上のあらゆるライティングを.mdフォーマットにしたら.mdがどんどんたまっていくことに…

これ、PDFにして美しく整形できないかな?と調べてみたら、

Pandoc&TeXを使うのが自由度も高くてよさげだとわかった。今回の記事はその忘備録です。

環境

OSWindows 10 Pro (22H2)
Python3.11.1
Pandoc2.19.2
TeX Live2022

ここまでの細かい手順は割愛。親切に書いてくださっているブログがいくつかあったし、今回のようなマニアックなことにチャレンジしようというスキルレベルの人なら特に詰まることもないと思う。

ただTeXのダウンロード&インストールはたとえ1G契約の光回線でも「あれ、フリーズした?」というくらい時間がかかるので留意メモ。

ソースコード

settings.json(設定ファイル)

{
    "pandoc_path":"D:/Program Files/Pandoc",
    "wkhtmltopdf_path":"D:/Program Files/Pandoc/wkhtmltopdf/bin",
    "header":"D:/data/tex/preamble.tex",
    "metadata_file":"D:/data/tex/metadata.yaml",
    "template":"D:/data/tex/template.tex",
    "source_md_dir":"D:/data/md",
    "dest_pdf":"D:/data/tex/output.pdf"
}

直書きでもよかったけど一応設定は外だしに。

preamble.tex

\usepackage[table]{xcolor}

% \usepackage[dvipdfmx]{graphicx}

% フォント設定
\usepackage{luatexja}
\usepackage[no-math]{luatexja-fontspec}
\usepackage[sourcehan-jp]{luatexja-preset}

% 箇条書きの設定
\usepackage{enumitem}
\setlistdepth{20}
\renewlist{itemize}{itemize}{20}
\setlist[itemize]{label=\textbullet}
\setmainfont{IPAPMincho}
\setsansfont{IPAPGothic}
\setmonofont{IPAGothic}

\definecolor{lightgray}{gray}{0.9}
% 表の行の色を互い違いに変える
\let\oldtabular\tabular
\let\endoldtabular\endtabular
\renewenvironment{tabular}{\rowcolors{2}{white}{lightgray}\oldtabular}{\endoldtabular}

\let\oldlongtable\longtable
\let\endoldlongtable\endlongtable
\renewenvironment{longtable}{\rowcolors{2}{white}{lightgray}\oldlongtable} {
\endoldlongtable}

metadata.yaml

documentclass: ltjarticle
figureTitle: "図"
tableTitle: "表"
listingTitle: "コード"
figPrefix: "図"
eqnPrefix: "式"
tblPrefix: "表"
lstPrefix: "コード"
geometry: a4paper
geometry: margin=3cm
variables:
  toc-title: "目次"
  table-use-row-colors: true

template.tex

長いので割愛。表紙として使いました。

md_to_pdf.py

import os
import glob
import subprocess
import pathlib
import json

# 設定ファイル読み込み
json_file = open('settings.json', 'r', encoding="utf_8_sig")
json_data = json.load(json_file)
print(f"設定ファイル「settings.json」を読み込みました")

# Pathの設定
os.environ['PATH'] = '{};{}'.format(json_data["pandoc_path"], os.environ['PATH'])
os.environ['PATH'] = '{};{}'.format(json_data["wkhtmltopdf_path"], os.environ['PATH'])
print(f"環境変数を設定しました")

# ディレクトリ変更
os.chdir(json_data["source_md_dir"])
print(f"カレントディレクトリを変更しました")

md_files = ""
for f in glob.glob(json_data['source_md_dir'] + "/*.md"):
    md_files += os.path.split(f)[1]
    md_files += " " # ファイルはスペースで区切る
md_files.rstrip()

cmd = f"pandoc \
    -o {json_data['dest_pdf']} \
    --pdf-engine=lualatex \
    -V documentclass=ltjarticle \
    --template={json_data['template']} \
    --toc \
    --include-in-header={json_data['header']} \
    --metadata-file={json_data['metadata_file']} \
    {md_files}"\

print(f"pandocプロセスを実行しています…")

return_code = 0
try:
    # pandoc実行
    # shell=Trueにすることでリスト型ではなくstr型でコマンドを解釈させる
    res = subprocess.run(cmd, shell=True, stdout=subprocess.PIPE, encoding='UTF-8') 
except subprocess.CalledProcessError as e:
    return_code = e.returncode
    print(e.cmd)
    print(e.returncode)
    print(e.output)
    print(e.stdout)
    print(e.stderr)

if return_code == 0:
    # 出力先フォルダを開く
    subprocess.Popen(["explorer", pathlib.Path(json_data["dest_pdf"]).parent], shell=True)
    print("プロセスを正常に終了しました")

このpyを実行すると設定ファイルの「dest_pdf」で指定したPDFとして書き出される。

タイトルとURLをコピーしました