2015年5月9日土曜日

PandocのHTML出力でGFMとカスタムテンプレートを使う

PandocでMarkdownをHTMLへ変換

ドキュメント変換ツール Pandoc は様々な入出力形式に対応したコマンドラインツールです。多くの派生版 Markdown への対応や Pandoc による拡張 Markdown などの機能があり、柔軟な Markdown 変換ツールとして興味深いツールです。また、LaTeX を使った PDF 出力機能もそのひとつです。

この投稿では Pandoc を使って Markdown テキストを HTML へ変換する方法を簡単に紹介しています。

使用環境:Windows7 64bit, pandoc 1.13.2, Firefox 37.0.2



Pandocをインストール

Windows 用をダウンロード

最新版 pandoc-1.13.2-windows.msi をインストール。



Pandocを使ってみる

インストールが完了したら手始めに Pandoc の動作確認を兼ねて、Markdown テキストを HTML に変換してみましょう。ここではファイルを使わずに標準入出力を使って試します。

  1. コマンドプロンプトでpandocと入力
  2. #Hello Pandocを入力
  3. Crtl + Zキーを押して EOF を入力
  4. HTML に変換された結果が画面に表示されます。

      >pandoc
      #Hello Pandoc
      ^Z
      <h1 id="hello-pandoc">Hello Pandoc</h1>
      

このように入出力ファイルを指定しない場合 Pandoc は入力に標準入力を、出力に標準出力を使用します。また、入出力フォーマットを明示しない場合は入力フォーマットに Markdown を、出力フォーマットに HTML が選ばれます。

実際の Markdown テキストを HTML へ変換する場合は入出力ファイルやフォーマット、テンプレートなどを指定して使います。

pandoc -f markdown input.md -t html5 -s -o output.html

コマンドラインの-sオプションで標準テンプレートを指定すると、出力フォーマットに合わせた標準テンプレートが選択されます。この例の場合、適用されるのは HTML 出力用のhtml5テンプレートです。

html5テンプレートの内容は次のコマンドで確認できます。

pandoc -D html5

また css や MathJax の設定(後述)を含んだカスタムテンプレート(後述)を使用することも可能です。



MarkdownファイルをHTMLファイルへ変換する例

Pandoc では標準の Markdown のほか "GitHub flavored Markdown" もサポートされています。このフォーマットを使用する場合は入力フォーマットにmarkdown_githubを指定します。

  • markdown_github オプションを使って HTML に変換

    pandoc -f markdown_github input.md -t html5 -s -o output.html
    
  • markdown_github オプションで CSS を含んだ HTML に変換。

    pandoc -f markdown_github input.md -c github.css -t html5 -s -o output.html
    

    この例ではカレントフォルダのgithub.cssが HTML 内にリンクされます。このファイルは、はじめから Pandoc に同梱されているわけではないので自分で用意する必要があります。例えば"Github Markdown CSS - for Markdown Editor Preview"などを参考にして作成します。



「段落内の強制改行」を無効化する

Pandoc の拡張 Markdown では、フォーマット名と拡張文字列を使って機能をコントロールします。フォーマット名に拡張文字列を+で結合するとその機能を有効に、-で結合するとその機能が無効化されます。

この例では-hard_line_breaksを結合して「段落内の強制改行」を無効化しています。

pandoc -f markdown_github-hard_line_breaks ^
input.md -c github.css -t html5 -s -o output.html


Markdownテキストに生HTMLを記述

標準の Markdown では、テキスト内に記述した生の HTML はそのまま出力されます。Pandoc でこの機能を有効にするには+raw_htmlオプションを使います。これで Markdown テキスト内に生の HTML を記述できるようになります。

pandoc -f markdown_github+raw_html ^
input.md -c github.css -t html5 -s -o output.html


コードブロックの行番号表示とシンタックスハイライト

GFM の"Fenced code blocks"は、コードブロックを貼り付ける時のインデントが不要なのでとても便利です。

さらに Pandoc は行番号表示やシンタックスハイライトまでサポートしています。この機能を有効にするには+fenced_code_attributesオプションを使います。

pandoc -f markdown_github+fenced_code_attributes ^
input.md -c github.css -t html5 -s -o output.html

例えば、言語に"Ruby"を指定、行番号を表示、開始行を 100 に指定する場合は、コードブロックの属性値をこのように記述します。開始行のstartFrom="100"を省略すると 1 から始まります。

```{.ruby .numberLines startFrom="100"}
puts 'Hello Pandoc!'
```

生成される HTML はこのようになります。.ruby.numberLinesの記述からわかるように、この値はクラスに設定されます。もちろん#fooなら ID に設定されます。

<table class="sourceCode ruby numberLines" startFrom="100">
  <tr class="sourceCode">
    <td class="lineNumbers">
      <pre>100</pre>
    </td>
    <td class="sourceCode">
      <pre>
        <code class="sourceCode ruby">
          puts <span class="st">&#39;Hello Pandoc!&#39;</span>
        </code>
      </pre>
    </td>
  </tr>
</table>

コードブロックのシンプルな記述方法は言語名だけを記述します。この場合はシンタックスハイライトのみ行われます。

```ruby
puts 'Hello Pandoc!'
```

生成される HTML では言語名がクラスに設定されています。

<pre class="sourceCode ruby">
  <code class="sourceCode ruby">
    puts <span class="st">&#39;Hello Pandoc!&#39;</span>
  </code>
</pre>


数式を含んだHTMLを出力する

HTML で数式を扱う場合 MathJax を使うと便利です。MathJax は、数式や LaTeX コマンドを解釈してブラウザで表示できるように変換してくれます。

Markdown の記述に GFM の書式を使い css を追加、MathJax で数式を表示する場合はこのようなコマンドを実行します。

pandoc -f markdown_github-hard_line_breaks ^
input.md -c github.css -t html5 -s ^
--mathjax=https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML ^
-o output.html


カスタムテンプレートを使う

カスタムテンプレートを作っておくと、あらかじめ MathJax のオプション設定や css ファイル等を追加することができます。カスタムテンプレートを簡単に作るには、標準のテンプレート雛形として利用します。

はじめに、次のコマンドを実行してカスタムテンプレートmytemplate.htmlを作成します。

pandoc -D html5 > mytemplate.html

このテンプレートを使用する場合は、コマンドに--mytemplate=mytemplate.htmlオプションを追加します。

pandoc -f markdown input.md -t html5 ^
--template=mytemplate.html -o output.html

カスタムテンプレートの例

次のコードをカスタムテンプレートの</head> の直前に追加すれば、css ファイルと MathJax オプションの設定ができます。

この例ではカレントフォルダの github.css をリンクしています。また、MathJax のオプション設定では日本語の数式メニューやエラーメッセージの表示、数式のズーム設定。インライン数式のデリミタに$...$を使用できるようにしています。

<link rel="stylesheet" href="github.css">
<script type="text/x-mathjax-config">
  MathJax.Hub.Config({
    menuSettings: {locale: "ja"},
    extensions: ["tex2jax.js", "MathMenu.js", "MathZoom.js"],
    TeX: {
      extensions: ["AMSmath.js", "AMSsymbols.js", "noErrors.js", "noUndefined.js"],
      noErrors: {disabled: true},
      noUndefined: {disabled: true}
    },
    jax: ["input/TeX", "output/HTML-CSS"],
    tex2jax: {
      inlineMath: [["$$","$$"], ["\\(","\\)"]],
      displayMath: [["$$$$","$$$$"], ["\\[","\\]"]],
      processEscapes: true
    }
  });
</script>
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML" type="text/javascript"></script>

インライン数式のデリミタ$...$について

インライン数式のデリミタは、他にもう一つの設定方法があります。それは、Pandoc の Markdown 拡張書式に、tex_math_dollarsを追加して--mathjaxオプションを指定します。この場合入力テキスト中の$...$\(...\)に、$$...$$\[...\]に変換して出力されます。

2つの設定方法の違い

  • MathJaxのオプションで設定する場合

    テンプレートファイルにtex2jax: { ... }を記述してインライン数式の$...$を有効にする場合は、単独の$記号を表示するときにエスケープしなければなりません。例えばPrice: $100を表示するにはPrice: \$100と記述します。

  • Pandocのオプションで設定する場合

    Pandoc の Markdown 拡張書式tex_math_dollarsの追加と--mathjaxオプションを指定する場合は、Pandoc が$で囲まれた範囲を認識して、数式か数式でないかを判断してくれます。そのためPrice: $100の表示では$記号のエスケープが不要になります。

記述の容易さでは後者の Pandoc オプションで設定するほうが便利かもしれません。その場合は上記コードのtex2jax: { ... }の部分を削除することで、デリミタ以外の MathJax オプションをテンプレートファイルで設定することができます。

後者の Pandoc オプションで設定する場合は次のようなコマンドを実行します。

pandoc -f markdown_github-hard_line_breaks+tex_math_dollars ^
input.md -t html5 --mathjax ^
--template=mytemplate.html ^
-o output.html

テンプレート内に MathJax スクリプトを記述している場合コマンドラインの--mathjaxオプションの指定は不要に思えますが、MathJax が受け取る TeX 形式で数式を出力するためにこのオプションが必要です。なぜなら Pandoc のデフォルトの数式出力では可能な限り Unicode 文字で数式を出力しようとします。



YAMLメタデータブロック

テンプレート内のプレースホルダ($記号で囲まれた変数)を使うと、テンプレートにメタデータを流し込むことができます。Pandoc ではメタデータの流しこみ用にいくつかの方法が用意されていますが、 YAML メタデータブロックを使うと汎用性が高まります。

Pandoc のテンプレートに YAML メタデータブロックを流し込む場合はあらかじめメタデータブロックを別ファイルまたは Markdown テキストの中に作成しておきます。 YAML メタデータブロックは---で始まり、---または...で終ります。

  • テキスト中に記述する場合の注意点は、YAML メタデータブロックの直前に空行を入れることです。ただし、テキストの先頭に記述する場合に限り、この空行は不要です。

  • 別ファイルに作成した YAML メタデータブロックを使用する場合はコマンドラインでファイル名を指定します。例えば YAML メタデータブロックを記述したファイルtest.yamlを指定する場合、次のようなコマンドを実行します。

pandoc -f markdown input.md test.yaml ^
-s -c github.css -t html5 ^
-o output.html

GFM の場合は+yaml_metadata_blockオプションを使います。

pandoc -f markdown_github+yaml_metadata_block ^
input.md test.yaml -s -c github.css -t html5 ^
-o output.html

複数の入力ファイルを指定した場合 Pandoc は、処理を開始する前にファイルとファイルの間に空行を追加してそれぞれのファイルを結合します。前述の YAML メタデータブロックの直前に空行を入れる理由はこのためです。



YAMLを使ったテンプレートの使用例

デフォルトテンプレートには、いくつかのプレースホルダが既に用意されています。実際に YAML メタデータの流し込みを試してみましょう。次の例では入力ファイルinput.mdのテキストの先頭に YAML メタデータブロックを記述しています。

input.md

---
pagetitle: YAMLテスト
title: YAML メタデータテスト
subtitle: サブタイトル
author:
- foo
- bar
date: May 5, 2015
---

#こんにちはPandoc

デフォルトテンプレートを使用するため-sオプションでコマンドを実行します。

pandoc -f markdown input.md ^
-s -c github.css -t html5 -o output.html

GFM の場合は+yaml_metadata_blockオプションを使います。

pandoc -f markdown_github+yaml_metadata_block ^
input.md -s -c github.css -t html5 ^
-o output.html

実行すると YAML メタデータが流し込まれた HTML ファイルが出力されます。プレースホルダの記述方法は、テンプレートと出力されたHTMLファイルを見比べると分かりやすいです。テンプレートの内容はpandoc -D html5で確認できます。



Pandoc変数

テンプレート内のプレースホルダは Pandoc 変数を使って制御することができます。それではテンプレートと出力されたHTMLファイルを見比べてみましょう。

条件分岐

例えば変数$subtitle$では条件分岐が使われています。

この場合、変数$subtitle$に値がセットされていれば
<h1 class="subtitle">$subtitle$</h1>を適用します。

$if(subtitle)$
  <h1 class="subtitle">$subtitle$</h1>
$endif$

出力結果を見ると、このようになっています。

<h1 class="subtitle">これはサブタイトル</h1>

同様に変数$title$では、変数の値がセットされていない場合
<header>...</header>の行全体が適用されません。

$if(title)$
  <header>
  <h1 class="title">$title$</h1>
  $if(subtitle)$
    <h1 class="subtitle">$subtitle$</h1>
  $endif$
  $for(author)$
    <h2 class="author">$author$</h2>
  $endfor$
  $if(date)$
    <h3 class="date">$date$</h3>
  $endif$
  </header>
$endif$

繰り返し

例えば変数$author$ではリスト形式で複数の値がセットされています。このように変数の値が複数ある場合は$for$キーワードを使って値を取得できます。

この場合変数$author$に値がセットされていれば、
値毎に<h2 class="author">$author$</h2>を適用します。

$for(author)$
  <h2 class="author">$author$</h2>
$endfor$

出力結果を見ると、このようになっています。

<h2 class="author">foo</h2>
<h2 class="author">bar</h2>

このようにテンプレートと YAML メタデータブロックを使えば、柔軟なメタデータの流しこみが可能になります。



まとめ

簡単ですが Pandoc の HTML 変換を紹介しました。Pandoc には他にも多くの機能があります、興味を持った方はユーザーズガイドを読んでみてください。

本家ユーザーズガイド

日本語ユーザーズガイド

参考までに、今回使用したオプションを全てコマンドラインに適用すると こうなります。

pandoc -f markdown_github-hard_line_breaks^
+raw_html+fenced_code_attributes^
+tex_math_dollars+yaml_metadata_block ^
input.md -t html5 ^
--mathjax --template=mytemplate.html ^
-o output.html

付録

この投稿で使用したカスタムテンプレートと css を載せておきます。

mytemplate.html


github.css

0 件のコメント :