pandoc.py 技術ドキュメント

プログラムの動作

pandoc.py は、Pandocツールをラップし、MarkdownファイルをMicrosoft Word文書(.docx)、PowerPointプレゼンテーション(.pptx)、またはHTMLファイル(.html)に変換するためのユーティリティです。Pandocの複雑なコマンドラインオプションを抽象化し、よりシンプルで使いやすいインターフェースを提供することを目的としています。

主な機能:

  • Markdown変換: 指定されたMarkdownファイルを、docx、pptx、htmlのいずれかの形式に変換します。

  • Pandoc実行ファイルの自動検索: システムのPATH、環境変数 pandoc_path、または tkProg_path に基づいてPandoc実行ファイルを自動的に探し出します。

  • テンプレートファイルの自動検索: 変換に使用するテンプレートファイル(.docx, .pptx)を、カレントディレクトリまたはスクリプトの配置ディレクトリから自動的に探し出します。

  • デフォルトテンプレートの生成: Pandocが提供するデフォルトのWordまたはPowerPointテンプレートを簡単に生成できます。これにより、ユーザーはスタイルをカスタマイズするためのベースファイルを得られます。

  • Markdownの自動修正: Pandocの変換プロセスで問題を引き起こしやすいMarkdownの記述形式(特にAIが生成するMarkdownで発生しやすい問題)を自動的に修正します。具体的には、不正なYAMLフロントマターの無効化、存在しない画像やリンクの無害化、数式表記の正規化などを行います。

  • HTML変換の拡張: MathMLによる数式表示やカスタムCSSの適用など、HTML出力に関するオプションを提供します。

解決する課題:

  • Pandocの複雑なコマンドラインオプションを覚えたり、毎回入力したりする手間を省きます。

  • Pandocの実行パスやテンプレートのパスを手動で指定する煩わしさを解消します。

  • Markdownファイルに存在する可能性のある、Pandocの変換を失敗させる記述(例: 不正なYAML、存在しないファイルへのリンク、特殊な数式記法など)を自動的に検出し、修正することで変換の成功率を高めます。

  • ドキュメント作成のワークフローを効率化し、Markdownからさまざまな形式のドキュメントを生成する際の摩擦を軽減します。

原理

pandoc.py は、外部プログラムである pandocsubprocess モジュールを通じて実行することで変換処理を行います。主要な機能は以下のアルゴリズムに基づいています。

  1. Pandoc実行ファイルの探索: find_pandoc() 関数は、以下の優先順位で pandoc 実行ファイルを探します。

    • 環境変数 pandoc_path で指定されたパス。

    • 環境変数 tkProg_path が設定されている場合、そのパスを基準としたデフォルトのインストールパス(Windowsでは tkApp_Win/pandoc/pandoc.exe、Linuxでは tkApp_Linux/pandoc/pandoc)。

    • システムの PATH 環境変数内。 見つかった場合はそのフルパスを、見つからない場合は単に "pandoc" を返して PATH 探索に委ねます。

  2. テンプレートファイルの探索: find_template() 関数は、指定されたテンプレートファイル(例: template.docx)を以下の優先順位で探します。

    • スクリプトが実行されているカレントディレクトリ。

    • pandoc.py スクリプト自体が配置されているディレクトリ。 見つかった場合はそのフルパスを返します。

  3. Markdownの自動修正 (correct_markdown_pandoc_error): この関数は、Pandocが変換エラーを起こしやすい一般的なMarkdownの記述を正規化・修正します。

    • YAMLフロントマターの処理: Markdownファイルの冒頭に存在する可能性のあるYAMLフロントマターを正規表現 $r'^---\s*\n(.*?)\n---\s*\n'$ で抽出し、pyyaml ライブラリの yaml.safe_load() で有効性をチェックします。 もしYAMLとして不正な記述である場合、PandocがこれをYAMLフロントマターと誤解釈してエラーを出すのを防ぐため、--- の前後に空行を挿入してMarkdownの水平線として扱われるように修正します。

    • 水平線 --- の安全化: YAMLフロントマターではない一般的な水平線 (---) についても、その前後に空行がない場合にPandocが解析エラーを起こすことがあるため、安全のために前後に空行を挿入します。

    • 存在しない画像/リンクの無害化: Markdownの画像 (![]()) やリンク ([]()) の構文において、参照されているファイル(例: image.png)が実際に存在しない場合、Pandocはエラーを発生させることがあります。これを回避するため、(!?\[.*?\]\((.*?)\)) の正規表現でこれらの構文を検出し、base_dir からの相対パスでファイルが存在するか確認します。ファイルが存在しない場合、![]() または []() の全体をバッククォートで囲み、Pandocによってコードスパン(インラインコード)として扱われるように修正します。これにより、エラーではなく無害な表示に変換されます。

    • 数式の正規化:

      • $$ inline $$ のようなインラインに書かれた二重ドル記号による数式ブロックを、Pandocが推奨する標準的なブロック数式形式に変換します。これは、\$\$(.+?)\$\$ の正規表現でマッチさせ、マッチした内容を $$\n{content}\n$$ の形式に置き換えることで実現されます。

      • 生成AIがよく出力する $[...]$$(...)$\[...\]\(...\) のような数式表記も、同様に $$\n{content}\n$$ のブロック数式形式に変換します。これは、\\\[\s*(.+?)\s*\\\]\\\(\s*(.+?)\s*\\\) の正規表現でそれぞれ検出されます。

  4. 文字コードの推定と読み込み (read_text_with_chardet): 入力ファイルはまずバイナリモードで読み込まれ、chardet ライブラリを使用して文字コードが推定されます。その後、推定された文字コードでテキストファイルとしてデコードされます。これにより、様々なエンコーディングのMarkdownファイルを安全に処理できます。

  5. Pandocコマンドの構築と実行: convert_with_pandoc() 関数は、解析されたコマンドライン引数(変換ターゲット、入力ファイル、出力ファイル、テンプレート、CSS、MathMLオプションなど)に基づいて、適切な pandoc コマンドライン文字列を構築します。 例: pandoc input.md -o output.docx --reference-doc template.docx このコマンドは subprocess.run() を使って実行され、エラーが発生した場合は適切なメッセージが表示されます。

  6. HTML出力の修正 (correct_html): --mathml オプションが指定されている場合、Pandocが生成したHTMLコンテンツを、MathJaxライブラリを読み込むためのスクリプトタグを含む基本的なHTMLテンプレートでラップします。これにより、Webブラウザで数式が正しくレンダリングされるようになります。

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
  <script id="MathJax-script" async
    src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/mml-chtml.js"></script>
</head>

<body>
<!-- Pandocによって生成されたコンテンツ -->
</body>
</html>

必要な非標準ライブラリとインストール方法

pandoc.py を実行するために、以下の非標準Pythonライブラリが必要です。

  • chardet: ファイルの文字コードを自動的に推定するために使用されます。

  • pyyaml: MarkdownファイルのYAMLフロントマターを解析し、その有効性を検証するために使用されます。

これらのライブラリは pip コマンドを使用してインストールできます。

pip install chardet pyyaml

また、プログラムの核心機能は外部ツールである Pandoc に依存しています。Pandocがシステムにインストールされ、その実行パスがPythonスクリプトから認識できるように設定されている必要があります。Pandocのインストール方法については、公式ドキュメントを参照してください。

必要な入力ファイル

pandoc.py が必要とする主な入力ファイルは以下の通りです。

  1. Markdownファイル (.md): --infile または -i オプションで指定される、変換元のテキストファイルです。標準的なMarkdown記法で記述されていることを想定していますが、一部の表記(数式など)は自動修正機能によってPandocが処理しやすい形に正規化されます。YAMLフロントマターが含まれている場合、それも解析されます。

  2. テンプレートファイル (.docx, .pptx) (オプション): --template または -t オプションで指定される、変換後のWord文書やPowerPointプレゼンテーションのスタイルを定義するためのファイルです。Pandocは、このテンプレートを基にして出力ファイルのスタイルを適用します。指定しない場合はPandocの組み込みデフォルトスタイルが使用されますが、docx/pptxへの変換ではカスタムテンプレートの使用が強く推奨されます。

  3. カスタムCSSファイル (.css) (オプション): --css オプションで指定される、HTML変換時に適用されるスタイルシートファイルです。Webページの見た目をカスタマイズするために使用します。

生成される出力ファイル

pandoc.py は、以下の種類のファイルを出力として生成します。

  1. Word文書 (.docx): --convert docx オプションでMarkdownファイルをWord形式に変換した結果として生成されます。ファイル名は --outfile オプションで指定されない場合、入力ファイル名(例: input.md)に基づいて input.docx となります。

  2. PowerPointプレゼンテーション (.pptx): --convert pptx オプションでMarkdownファイルをPowerPoint形式に変換した結果として生成されます。ファイル名は --outfile オプションで指定されない場合、入力ファイル名(例: input.md)に基づいて input.pptx となります。

  3. HTMLファイル (.html): --convert html オプションでMarkdownファイルをHTML形式に変換した結果として生成されます。ファイル名は --outfile オプションで指定されない場合、入力ファイル名(例: input.md)に基づいて input.html となります。

  4. Pandocテンプレートファイル (reference.docx, reference.pptx): --make_template docx または --make_template pptx オプションを使用し、--template で出力ファイル名を指定した場合に生成されます。これらはPandocのデフォルトスタイルを定義した空のWord文書またはPowerPointプレゼンテーションであり、ユーザーがカスタマイズするためのベースとして利用できます。

  5. 一時的な修正済みMarkdownファイル (.corrected.md): pandoc.py のMarkdown自動修正機能が動作すると、元の入力ファイル名に .corrected.md のサフィックスを付けた一時ファイル(例: input.corrected.md)が生成されます。このファイルはPandocへの実際の入力として使用されます。通常、このファイルは変換が完了した後も残り、デバッグ用途に利用できます。

コマンドラインでの使用例 (Usage)

基本的なコマンドライン引数とそれらの意味は以下の通りです。

python pandoc.py [-h] [--pandoc_path P] [--infile I] [--outfile O] [--template T]
                [--convert {docx,pptx,html,}] [--toc TOC] [--mathml]
                [--css CSS] [--make_template {docx,pptx}] [--smart_conversion SMART_CONVERSION]
                [--no-yaml] [--verbose] [--pause PAUSE]
  • --pandoc_path, -p: pandoc 実行ファイルのパスを指定します。指定しない場合、自動的に検索されます。

  • --infile, -i: 変換元のMarkdownファイルのパスを指定します。--convert 使用時に必須です。

  • --outfile, -o: 出力ファイル名を指定します。指定しない場合、入力ファイル名から自動的に決定されます。

  • --template, -t: 変換に使用するテンプレートファイルのパスを指定します(例: .docx, .pptx)。テンプレート生成時にも使用されます。

  • --convert, -c: 変換するターゲット形式を指定します。docx, pptx, html のいずれか、または空文字列を指定します(空文字列の場合は --outfile の拡張子で判断)。

  • --toc: ドキュメントに目次を生成します(Wordへの変換時のみ有効)。0 または 1 を指定。

  • --mathml: HTML変換時に数式をMathML形式で表示します。

  • --css: HTML変換時に適用するカスタムCSSファイルのパスを指定します。

  • --make_template: デフォルトのPandocテンプレートを生成します。docx または pptx を指定。--template で出力先ファイル名を指定する必要があります。

  • --smart_conversion: Pandocの"smart"拡張を有効/無効にします(例: --- をem-dashに変換)。デフォルトは無効(0)。1 で有効化。

  • --no-yaml: 入力MarkdownファイルをYAMLメタデータブロックとして解釈しません。

  • --verbose: 詳細な実行ログを出力します。

  • --pause: プログラム終了時にEnterキーの入力を要求するかどうかを指定します(0 で無効、1 で有効)。

コマンドラインでの具体的な使用例

1. Wordテンプレートの生成

template_textbook.docx という名前で、PandocのデフォルトWordテンプレートを生成します。

python pandoc.py --make_template docx --template template_textbook.docx

実行結果の説明: カレントディレクトリまたはスクリプトのあるディレクトリに template_textbook.docx というファイルが作成されます。このファイルを開き、Wordのスタイル設定を変更することで、Markdownから生成されるWord文書の見た目をカスタマイズできます。

2. PowerPointテンプレートの生成

template_slide.pptx という名前で、PandocのデフォルトPowerPointテンプレートを生成します。

python pandoc.py --make_template pptx --template template_slide.pptx

実行結果の説明: カレントディレクトリまたはスクリプトのあるディレクトリに template_slide.pptx というファイルが作成されます。このファイルを開き、PowerPointのマスタースライド設定を変更することで、Markdownから生成されるスライドの見た目をカスタマイズできます。

3. MarkdownからWord文書への変換

lecture_textbook.md を入力として、template_textbook.docx をテンプレートに使用してWord文書 lecture_textbook.docx を生成します。

python pandoc.py --convert docx --infile lecture_textbook.md --template template_textbook.docx --toc 1

実行結果の説明:

  • lecture_textbook.md が読み込まれ、Pandocが処理しやすいように自動修正されます(例: lecture_textbook.corrected.md が一時的に生成される)。

  • template_textbook.docx がテンプレートとして適用されます。

  • lecture_textbook.docx という名前のWord文書が出力され、Markdownの内容がWord形式に変換されます。

  • --toc 1 により、生成されるWord文書には目次が自動的に挿入されます。

4. MarkdownからPowerPointプレゼンテーションへの変換

lecture_slide.md を入力として、template_slide.pptx をテンプレートに使用してPowerPointプレゼンテーション lecture_slide.pptx を生成します。

python pandoc.py --convert pptx --infile lecture_slide.md --template template_slide.pptx

実行結果の説明:

  • lecture_slide.md が読み込まれ、自動修正されます。

  • template_slide.pptx がテンプレートとして適用されます。

  • lecture_slide.pptx という名前のPowerPointプレゼンテーションが出力され、Markdownの各セクションがスライドとして構成されます。

5. MarkdownからHTMLファイルへの変換(MathML対応)

lecture_textbook.md を入力として、MathMLを使用して数式を表示できるHTMLファイル lecture_textbook.html を生成します。

python pandoc.py --convert html --infile lecture_textbook.md --mathml

実行結果の説明:

  • lecture_textbook.md が読み込まれ、自動修正されます。

  • lecture_textbook.html という名前のHTMLファイルが出力されます。

  • このHTMLファイルには、--mathml オプションにより、MathJaxライブラリを読み込むスクリプトが挿入され、HTMLをブラウザで開くと数式が適切にレンダリングされます。

6. MarkdownからHTMLファイルへの変換(カスタムCSS適用)

lecture_textbook.md を入力として、custom_style.css を適用したHTMLファイル lecture_textbook.html を生成します。

python pandoc.py --convert html --infile lecture_textbook.md --css custom_style.css

実行結果の説明:

  • lecture_textbook.md が読み込まれ、自動修正されます。

  • lecture_textbook.html という名前のHTMLファイルが出力されます。

  • 生成されたHTMLファイルには、custom_style.css へのリンクが <head> セクションに挿入され、Webブラウザで開くとカスタムスタイルが適用されます。