BandersnatchとPandocの話

Bandersnatchは便利ですねという話とBandersnatchを見て知ったPandocの機能について書きます。

Bandersnatch

BandersnatchはMarkdownファイルをReveal.jsを使った格好いいスライドに変換するツールです。

使い方

GitHubプロジェクトに非常にわかりやすい導入方法があるのでそちらを参照しましょう。一応、こちらにも書いておきます。

  1. gitクライアントをインストールする
  2. PandocとNode.jsをインストールしてパスを通しておく
  3. リポジトリをクローン(git clone https://github.com/sansyo/bandersnatch.git sample)する
  4. sampleディレクトリでnpm installする
  5. sample/source/slides.mdを編集する
  6. sampleディレクトリでgruntを実行する

これだけでReveal.jsを使ったスライドができあがりす。一度npm installを済ませれば、あとはMarkdownの編集(とgrunt)するだけでスライドを更新できるのでとても楽です。

Pandoc

Bandersnatchでは、MarkdownからHTMLへの変換にPandoc(のコマンドラインツール、pandoc)を使っています。Bandersnatchの魔法はPandocが支えています(もちろんgruntも)。

PandocはMarkdownやHTMLなど、いろいろなファイルを別のフォーマットに変換するツールです。もちろんMarkdownもサポートしていますし、Markdownに対する拡張もいくつか追加されています。これらの拡張は最初から有効になっているものもありますし、pandocコマンドのオプションで有効・無効を切り替えることもできます。Bandersnatchではこれらの機能を活用してMarkdownからReveal.js用のHTMLを書き出しています。

--section-divs

--section-divsは見出しの構造をもとに、章や節を自動的にdiv要素やsection要素でくくる機能です。

たとえば、次のようなMarkdownファイルがあるとします。

# 見出し1

あああ

## 見出し2-1

いいい

### 見出し3

ううう

## 見出し2-2

えええ

このMarkdownからdiv要素でくくったHTMLを書き出すには以下のようにpandocコマンドを呼び出します。

pandoc --section-divs source.md

出力結果は次のようになります(視覚的にわかりやすいようにインデントを入れています)。

<div id="見出し1" class="section level1">
    <h1>見出し1</h1>
    <p>あああ</p>
    <div id="見出し2-1" class="section level2">
        <h2>見出し2-1</h2>
        <p>いいい</p>
        <div id="見出し3" class="section level3">
            <h3>見出し3</h3>
            <p>ううう</p>
        </div>
    </div>
    <div id="見出し2-2" class="section level2">
        <h2>見出し2-2</h2>
        <p>えええ</p>
    </div>
</div>

HTML5で出力する(-t html5オプション)とdiv要素ではなくsection要素でくくるようにになります。

pandoc -t html5 --section-divs source.md

出力結果は次のようになります(やはり、視覚的にわかりやすいようにインデントを入れています)。

<section id="見出し1" class="level1">
    <h1>見出し1</h1>
    <p>あああ</p>
    <section id="見出し2-1" class="level2">
        <h2>見出し2-1</h2>
        <p>いいい</p>
        <section id="見出し3" class="level3">
            <h3>見出し3</h3>
            <p>ううう</p>
        </section>
    </section>
    <section id="見出し2-2" class="level2">
        <h2>見出し2-2</h2>
        <p>えええ</p>
    </section>
</section>

(ただ、機械的に生成したsection要素が意味的に整合している場合は限られるかもしれません。)

また、機械的に生成されたid属性が気になる場合には、id属性を機械生成する拡張機能、auto_identifiersを無効にします。拡張機能の有効・無効もコマンドラインのオプションで設定できます。-f markdown(入力フォーマットはMarkdownという指定)の後ろに、有効する拡張機能+拡張機能形式、無効にする拡張機能-拡張機能形式で記述します。

auto_identifiersを無効にした場合のpandocコマンドは次のようになります。

pandoc -f markdown-auto_identifiers -t html5 --section-divs source.md

一応、id属性なしの出力結果も挙げておきます(やはり視覚的にわかりやすいようにインデントを入れています)。

<section class="level1">
    <h1>見出し1</h1>
    <p>あああ</p>
    <section class="level2">
        <h2>見出し2-1</h2>
        <p>いいい</p>
        <section class="level3">
            <h3>見出し3</h3>
            <p>ううう</p>
        </section>
    </section>
    <section class="level2">
        <h2>見出し2-2</h2>
        <p>えええ</p>
    </section>
</section>

テンプレート

Pandocでは、Markdownから生成されたHTMLを、テンプレートの中に入れて書き出すこともできます。

HTMLのテンプレートの例はたとえば次のようになります。Markdownから生成されたHTMLが入る場所には$body$と記述します。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>タイトルの指定方法はあとでやります</title>
</head>
<body>
<!-- ほげほげ -->
$body$
<!-- ふがふが -->
</body>
</html>

pandocコマンドで--template テンプレートファイルオプションを使うと、Markdownから生成したHTMLを、テンプレートに組み込んで出力することができます。

pandoc -t html5 --section-divs --template template.html source.md

出力結果も次に挙げます。$body$が記述されていた場所にMarkdownから生成されたHTMLが入っています。

<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>タイトルの指定方法はあとでやります</title>
</head>
<body>
<!-- ほげほげ -->
<section id="見出し1" class="level1">
<h1>見出し1</h1>
<p>あああ</p>
<section id="見出し2-1" class="level2">
<h2>見出し2-1</h2>
<p>いいい</p>
<section id="見出し3" class="level3">
<h3>見出し3</h3>
<p>ううう</p>
</section>
</section>
<section id="見出し2-2" class="level2">
<h2>見出し2-2</h2>
<p>えええ</p>
</section>
</section>
<!-- ふがふが -->
</body>
</html>

テンプレートではページのタイトルや著者、日付を参照することもできます(pandoc_title_block拡張機能(最初から有効))。Markdownファイルの先頭に、次のように「%」から始まる行を書くと、自動的にタイトル、著者や日付と認識され、テンプレートから変数として参照することができます。

% タイトル
% 著者1; 著者2; 著者3
% 2013年1月1日

参照する例を次に挙げます。

<h1>$title%</h1><!-- <h1>タイトル</h1> -->
<ol>
$for(author)$
<li>$author$</li><!-- <li>著者1</li><li>著者2</li>… -->
$endfor$
</ol>
<p>$date$</p><!-- <p>2013年1月1日</p> -->

まとめ

  • Bandersnatchを使うとReveal.jsを使ったスライドを簡単に作ることができる
  • Pandocには様々な機能があり、Bandersnatchはそれらを有効活用している