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][]

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

http://johnmacfarlane.net/pandoc/installing.html

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

```bash
pandoc -v
```


## [Node.js][]

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

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

```bash
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.json` の `devDependencies` に `grunt` のバージョンを指定します（例:  `grunt: "0.3.17"`）。

```bash
npm uninstall -g grunt
```

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

```bash
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ファイルのイメージ

こんな感じ。

![sample1.png](https://qiita-image-store.s3.amazonaws.com/0/37432/f628d727-5560-734b-10aa-c954f03000aa.png)

![sample2.png](https://qiita-image-store.s3.amazonaws.com/0/37432/3477b56f-34ef-2c0a-76b0-0d189fbb1195.png)

![sample3.png](https://qiita-image-store.s3.amazonaws.com/0/37432/1c86a263-c52b-bfcf-07c4-c5e55f41b72b.png)



# 自動タスク環境の構築

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

* `grunt-contrib-watch`
* `grunt-contrib-connect`
* `grunt-contrib-livereload`
* `connect-livereload` 

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


## `package.json`

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

```json
{
  "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`

```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レイアウトテンプレート

[Pandoc][]の[templates][]を利用します。

http://johnmacfarlane.net/pandoc/README.html#templates

各種フォーマットの[サンプル](https://github.com/jgm/pandoc-templates/) が公開されているので、
こちらを利用します。

https://github.com/jgm/pandoc-templates/blob/master/default.html5

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


```html
<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.json`の`devDependencies`に記載したプラグインをインストールします。

```bash
cd PATHTO_PROJECT
npm install
```

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

ターミナルを開いて、

```bash
grunt
```

を実行します。
![スクリーンショット 2014-02-20 21.20.23.png](https://qiita-image-store.s3.amazonaws.com/0/37432/0de751aa-461a-cfe1-9075-07c1f3547307.png)


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

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


# 感想

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

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




[Node.js]: http://nodejs.org/
[Grunt]: http://gruntjs.com/
[nodebrew]: https://github.com/hokaccha/nodebrew
[nvm]: https://github.com/creationix/nvm
[Pandoc]: http://johnmacfarlane.net/pandoc/
[templates]: http://johnmacfarlane.net/pandoc/README.html#templates
[highlight.js]: http://highlightjs.org/