Markdown+Pandoc+Gruntでリアルタイムプレビュー&オリジナルデザインのHTMLドキュメントを生成する


Githubなどの普及によりWebサービス上のドキュメントをMarkdown形式で書くことが多くなりました。
そのため、Markdownのプレビュー表示を行うツールやWebサービスなども多く登場してきました。

一方、プレビュー表示以外にも以下のような要望、欲求があると思います。

  • Webサービスに紐付かないドキュメントとして出力したい
  • デザインを自由に変更したい

顧客やユーザに提供する操作マニュアルやAPI仕様書をMarkdownで作成したいというケースです。

プレビュー表示レベルのものばかりで意外と欲求を満たすものがないのが現状です。
もしかしたら、あるかもしれませんが、今回は自分で小回りの効く環境を作ってみたいと思います。

プレビュー表示のみでよいのであれば、本記事は読み飛ばしてください。

事前準備

事前に以下のモジュールを利用できるようにしておいてください。

  1. Pandoc
  2. Node.js v0.10.x〜
  3. Grunt v0.4.x〜

Pandoc

公式サイトからインストーラを入手してください。

ターミナルからコマンドが通ることを確認します。

pandoc -v

Node.js

Node.jsは公式サイトから入手できるインストーラでもよいのですが、これからNode.js
を扱うことが多くなる方は、nodebrewnvmなどのNodeバージョン管理ツールを使って
インストールすることをおすすめします。

Proxy環境でnpmコマンドを扱う場合は、Proxy設定を忘れずに行います。

npm config set proxy http://proxy.yourcompany.com:XXXX/
npm config set https-proxy http://proxy.yourcompany.com:XXXX/
npm config set registry http://registry.npmjs.org/

Grunt

Gruntのv0.3.x(v0.4以前)をグローバルインストールしている場合は、アンイストールしてください。
他プロジェクトでv0.3.x系を使っている場合は、プロジェクトの package.jsondevDependenciesgrunt のバージョンを指定します(例: grunt: "0.3.17")。

npm uninstall -g grunt

grunt-cliをグローバルインストールします。

npm install -g grunt-cli

やりたいこと

  • MarkdownからオリジナルデザインのHTMLを出力
  • リアルタイムプレビュー(ブラウザ自動リロード)

ディレクトリ構造のイメージ。(npm install前&HTML生成前)

./
 + Gruntfile.js
 + index.md
 + package.json
 + style.css
 + style.html
 + node_modules/     ... npm install で追加される
 + index.html        ... 生成ファイル

出力されたHTMLファイルのイメージ

こんな感じ。

自動タスク環境の構築

リアルタイムプレビューを実現するために、

  • grunt-contrib-watch
  • grunt-contrib-connect
  • grunt-contrib-livereload
  • connect-livereload

MarkdownからHTMLへの変換に grunt-exec を使います。

package.json

まずは、package.json を書きます。ここでは、nameversionには適当なものを設定しておきます。

{
  "name": "PandocMarkdown2HtmlGenerator",
  "version": "1.0.0",
  "devDependencies": {
    "grunt": "~0.4.2",
    "grunt-contrib-watch": "~0.4.4",
    "grunt-contrib-livereload": "~0.1.2",
    "grunt-contrib-connect": "~0.5.0",
    "grunt-exec": "~0.4.2",
    "connect-livereload": "~0.3.0"
  }
}

Gruntfile.js

var path = require('path');

module.exports = function (aGrunt) {
  // The property points to the "package.json" file.
  // -----------------------------------------------
  var pkg = aGrunt.file.readJSON('package.json');
  var taskName;
  for (taskName in pkg.devDependencies) {
    if (taskName.substring(0, 6) === 'grunt-') {
      aGrunt.loadNpmTasks(taskName);
    }
  }

  var mountDir = function (aConnect, aPoint) {
    return aConnect.static(path.resolve(aPoint));
  };

  aGrunt.initConfig({

    // @see https://github.com/gruntjs/grunt-contrib-connect
    // ------------------------------------------------------
    connect: {
      options: {
        port: 8001,
        hostname: 'localhost'
      },
      dev: {
        options: {
          middleware: function (aConnect) {
            return [
              require('connect-livereload')(),
              mountDir(aConnect, '.')
            ];
          }
        }
      }
    },


    // @see https://github.com/jharding/grunt-exec
    // --------------------------------------------
    exec: {
      pandoc: {
        command: 'pandoc -s --toc --template=style.html -c style.css -o index.html index.md'
      }
    },


    // @see https://github.com/gruntjs/grunt-contrib-watch
    // ----------------------------------------------------
    watch: {
      pandoc: {
        files: ['**/*.md', '**/*.css', 'style.html'],
        tasks: ['exec:pandoc'],
        options: {
          livereload: true
        }
      }
    }
  });

  aGrunt.registerTask('default', ['connect', 'watch:pandoc']);
};

HTMLレイアウトテンプレート

Pandoctemplatesを利用します。

各種フォーマットのサンプル が公開されているので、
こちらを利用します。

ソースコードのハイライト機能を組み込みたい場合は、highlight.js を組み込むのが良いでしょう。

<link rel="stylesheet" href="http://yandex.st/highlightjs/7.3/styles/default.min.css">
<script src="http://yandex.st/highlightjs/7.3/highlight.min.js"></script>

スタイルシート

style.css を作成します。ここでは詳細を省略します。
より汎用的に扱うには、LESSの利用をおすすめします。

CSSサンプルについては、別途公開を検討したいと思います。
これを作るのが一番面倒:(

依存モジュールのインストール

package.jsondevDependenciesに記載したプラグインをインストールします。

cd PATHTO_PROJECT
npm install

ファイル監視とconnect-serverの起動

ターミナルを開いて、

grunt

を実行します。

Markdownの更新で pandocコマンドが自動実行します。
また、Chromeで http://localhost:8001 を開いておけば、
ファイル更新のタイミングで自動的にブラウザリロードが実行されます。

カレントディレクトリに index.html が出力されているので確認してみてください。

感想

環境作るまでがたいへん。

grunt-md2html-generator プラグイン(仮名)があるとうれしいですね(人任せ)。
カラーセットやレイアウトをカスタマイズできるオプションがあると直よし。