markdownより1ファイルなHTMLを吐き出すツール(md-standalone)を作った

markdownから1ファイルだけで依存関係のないHTMLを吐き出すだけのツールがなかった(軽く探してみただけなのであるかも)ので[ukyo/md-standalone](https://github.com/ukyo/md-standalone)を作ってみました。

# インストール

```
npm install -g md-standalone
```

# 簡単な使い方

```
mdst foo.md > foo.html
```

# オプション

`-h` でヘルプを参照できます。

```
mdst -h
Usage: mdst [options] path/to/doc.md

Options:
  -s, --style   Stylesheet path(css, scss or less).  [default: "/path/to/md-standalone/lib/style/style.scss"]
  -o, --output  Output path(default STDOUT).
  -l, --level   Headings level                       [default: "1-6"]
  -c, --code    Code Theme                           [default: "tomorrow-night-eighties"]
  -m, --minify  Minify
  -t, --toc     Toc Tree
  -j, --js      Js Path                              [default: "/path/to/md-standalone/lib/defaultRenderer.js"]
```

## `-s`, `--style`

独自のスタイルシートを指定します。css, scss, lessに対応してて、あとscssの`@import`等は内部でwebpackを使っているので、よしなに解決してくれるはずです。

## `-o`, `--output`

吐き出し先のパス。

```
mdst foo.md -o foo.html
```

## `-c`, `--code`

コードのシンタックスハイライト。[highlight.js/src/styles at master · isagalaev/highlight.js](https://github.com/isagalaev/highlight.js/tree/master/src/styles)から指定できます。

## `-m`, `--minify`

minifyします。結構遅いのでちょっと確認するみたいなときはこのオプションは指定しないのがおすすめ。

## `-t`, `--toc`

目次が出ます。

## `-l`, `--level`

目次が実際に出力される範囲を指定します。

```
# h2からh4
mdst foo.md -l 2-4 > foo.html
```

## `-j`, `--js`

カスタムレンダラを指定できます。解説は後述。


# カスタムレンダラ

デフォルトでは[md-standalone/defaultRenderer.js at master · ukyo/md-standalone](https://github.com/ukyo/md-standalone/blob/master/lib/defaultRenderer.js)が使われてて(以下の程度のもの)、これは独自のもので置き換えられます。

```js
require('../fontello/css/font-icon-embedded.css');
var html = require('mdHelper').getHtml();
var tocHelper = require('tocHelper');
var options = require('./options');

module.exports = function() {
  document.body.innerHTML = '<div id="md">' +html + '</div>';
  document.title = document.querySelector('h1,h2,h3,h4,h5,h6').textContent;

  if (!options.toc) return;
  var tocTree = tocHelper.trimTocTree(tocHelper.getTocTree(), options.level.top, options.level.bottom);
  var tocEl = document.createElement('div');
  tocEl.id = 'toc';
  tocEl.innerHTML = tocHelper.renderTocTree(tocTree);
  document.body.appendChild(tocEl);
  tocHelper.addTocBehavior();
};
```

## ヘルパーモジュール

`mdHelper`, `tocHelper`, `options`というヘルパーモジュールを使用できます。

```js
var mdHelper = require('mdHelper');
var tocHelper = require('tocHelper');
var options = require('options');
```

### `mdHelper.getHtml()`

変換されたhtmlを返します。

### `tocHelper.getTocTree()`

目次を返します(以下参照)。

```js
[
  {
    heading: {level: 1, text: foo, anchor: foo},
    children: [...]
  },
  ...
]
```

### `tocHelper.trimTocTree(tocTree, top, bottom)`

ヘッダの上限下限を決めてその範囲の目次を返します。

```js
var newTocTree = tocHelper.trimTocTree(tocTree, 2, 4)
```

### `tocHelper.renderTocTree(tocTree)`

上で説明したような構造の目次からhtml(文字列)を生成して返します。

### `tocHelper.addTocBehavior()`

ほとんどデフォルトの目次専用ですが、目次を開閉できるようにします。

### `options`

CLIオプションの一部を取得できます。

```js
{
  toc: true,
  level: {
    top: 1,
    bottom: 6
  },
  codeTheme: 'tomorrow-night-eighties'
}
```

# API

プログラムから使用できます。

```
npm install md-standalone
```

```js
var mdst = require('md-standalone');

mdst({
  mdPath: 'path/to/doc.md',
  jsPath: 'path/to/renderer.js',
  styleSheetPath: 'path/to/stylesheet.css',
  codeTheme: 'tomorrow-night-eighties',
  toc: true,
  minify: true,
  level: {
    top: 1,
    bottom: 6
  }
}, function(err, result) {
  // ...
});
```

# まとめ

[ukyo/md-standalone](https://github.com/ukyo/md-standalone)を作ってみました。CLIとしてでなく、markdown系ツールのエクスポートとか用途はありそうなので使ってみてください。それと、このツールを作ったときに得られた知見は[webpackを使ってコマンドラインツールを作る - Qiita](http://qiita.com/ukyo/items/d395f7775933a5fe9f60)にまとめたので、そちらもよろしければどうぞ。