sphinx, jsdoc, esdoc, typedocをdockerを使ってjavascriptのapiドキュメントを作ってみたメモ

## はじめに

気になっていたドキュメント作成ツールを試してみた。

作って比較した感想は以下。

* sphinx:かなり奇麗なドキュメントを作成してくれる。rstは不馴れなのでmarkdown
* jsdoc: 寂しい。簡単
* jsdoc-minami: jsdocに少しの手間で見た目がかなり良くなる。es5が混じるならこれかな。
* esdoc: es6でクラスを作るならこれがきれい。カバレッジがデフォルトなのもよさそう。jsdocほどの自由さはないので、古い記法が混じったりすると使いにくいかも。
* jsdoc-sphinx: そこそこの見た目とsphinxの統一感。rstファイルが出力されるので最後に編集できる。テンプレートが英語なので日本語で使うなら書き換えたほうがよいかも。
* sphinx-js: 見た目は一番好み。sphinxのautodocをjsで使えるようにしたもの。sphinx-apidocがjavascriptのソースで使えるならこれを選んでいた。索引を自動生成してくれるのも嬉しい。何か方法ないかなあ。
* typedoc: typedocは[以前作成したソース](http://qiita.com/hibohiboo/items/73b6da2d9f22eb2c1878)があったので、比較用に入れてみた。

[作成したページのサンプル - github.io](https://hibohiboo.github.io/develop/dist/docs/html/index.html)

## 動作環境

* windows10
* vagrant1.9.2
* virtualbox5.1
* ubuntu-16.04
* docker17.03
* docker-compose1.11.2

## ディレクトリ構成

```yaml
- project
  - bin # dockerのコマンド実行用のシェル
    - generate.sh        # ドキュメント作成
  - docker-compose.yml # docker設定ファイル
  - documentation_generator
    - esdoc
      - .esdoc.json # esdocの設定ファイル
    - jsdoc
      - .jsdoc.json # jsdocの設定ファイル
      - README.md   # jsdocで作成したドキュメントのindex用
    - sphinx
      - source
        + _static   # sphinxの静的ファイル格納用
        + _template # sphinxのテンプレート格納用
      - build.sh # 起動用
      - Makefile # 起動用
    - sphinx-js
      - source
        - conf.py # sphinxの設定（sphinx-js用)
    - Dockerfile # dockerファイル
  - typedoc
    - Dockerfile # typedoc用dockerファイル
    - package.json  # npmスクリプトを記述したファイル
    - tsconfig.json # typescript用設定
  - docs # sphinxで出力するドキュメントのソース
    - contents 
      + jsdoc-sphinx # jsdoc-sphinxから出力されるファイル格納用ディレクトリ
      + sphinx-js    # sphinx-jsを試すために作成したファイルをいれたディレクトリ
      - esdoc.md     # sphinxのマークダウンテスト用
      - jsdoc.md
      - sphinx.md
    - index.rst # sphinxの最初のインデックス用
  - src # apiを作成したいソースファイル
    - code.js
    - esdoc
      - MyClass.js
    - typedoc
      - es6.ts
  - dist # 作成されたドキュメント格納用ディレクトリ
    - docs
      - api
        + esdoc # esdocで作成されたapiドキュメント
        + jsdoc # jsdocで作成されたapiドキュメント
        + minami # jsdocのminamiテンプレートで作成されたapiドキュメント
        + typedo # typedocで作成されたapiドキュメント
      + doctrees # sphinxのドキュメントツリー
      + html # sphinxが作成するドキュメント
```


## ファイル

```yaml:docker-compose.yml
version: '2'
services:
  documentation_generator:
    build: ./documentation_generator
    volumes:
      # sphinxのMakefile
      - ./documentation_generator/sphinx/Makefile:/root/Makefile
      # sphinxの起動ファイル
      - ./documentation_generator/sphinx/build.sh:/root/build.sh
      # shpinxの生成するHTMLのテンプレート
      - ./documentation_generator/sphinx/source/_templates:/root/source/_templates
      # shpinxの静的HTMLファイル
      - ./documentation_generator/sphinx/source/_templates:/root/source/_static
      # sphinx-jsのコンフィグファイル
      - ./documentation_generator/sphinx-js/source/conf.py:/root/source/conf.py
      # esdocの設定ファイル
      - ./documentation_generator/esdoc/.esdoc.json:/root/.esdoc.json

      # jsdocの設定ファイル
      - ./documentation_generator/jsdoc/.jsdoc.json:/root/.jsdoc.json

      # jsdocのREADMEファイル
      - ./documentation_generator/jsdoc/README.md:/root/README.md
      # sphinxでコンパイルするときの開始ファイル
      - ./docs/index.rst:/root/source/index.rst
      # ドキュメントのフォルダ
      - ./docs/contents:/root/source/contents
      # ビルドされたファイルの格納ディレクトリ
      - ./dist/docs:/root/build
      # apiドキュメントを作成したいソースファイルの格納ディレクトリ
      - ./src:/root/src
  # typedoc
  documentation_generator_typedoc:
    build: ./typedoc
    volumes:
    # ビルドするソースファイル
    - ./src:/my_typedoc/src
    # ビルドファイルの出力先
    - ./dist/docs/api/typedoc:/my_typedoc/dist
    # コンテナ上のpackage.jsonを上書き
    - ./typedoc/package.json:/my_typedoc/package.json
    # typescriptの設定ファイル
    - ./typedoc/tsconfig.json:/my_webpack/tsconfig.json
```

```docker:document_genarator/Dockerfile
FROM python:3.6

# curlをインストール
RUN apt-get install -y curl

# node.jsをインストール
RUN curl -sL https://deb.nodesource.com/setup_6.x | bash -
RUN apt-get install -y nodejs

# gitをインストール
RUN apt-get install -y git

# jsdocをインストール
RUN npm install -g jsdoc

# sphinxをインストール
RUN pip install git+https://github.com/sphinx-doc/sphinx@stable

# sphinxのマークダウン記法を可能にするプラグイン
RUN pip install recommonmark 

# esdocのインストール
RUN npm install -g esdoc

# 作業ディレクトリに移動
WORKDIR /root

# jsdocテンプレートminamiのインストール
RUN npm init -y
RUN npm install --save-dev minami

# jsdocテンプレートjsdoc-sphinxのインストール
RUN npm install jsdoc-sphinx

# sphinx-jsのインストール
RUN pip install 'sphinx-js>=1.5,<2.0'

CMD ["/bin/sh", "/root/build.sh"]
```

```sh:document_genarator/sphinx/build.sh
cd /root && make html
```

```sh:document_genarator/sphinx/Makefile
# Makefile for Sphinx documentation
#

# You can set these variables from the command line.
SPHINXOPTS    =
SPHINXBUILD   = sphinx-build
PAPER         =
BUILDDIR      = build

# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif

# Internal variables.
ALLSPHINXOPTS   = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source

.PHONY: html
html:
	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
	@echo
	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
```

```py:document_genarator/sphinx-js/source/conf.py
import sys
import os
import shlex

# マークダウンが使用できるように設定
import recommonmark
from recommonmark.parser import CommonMarkParser
source_parsers = {
    '.md': CommonMarkParser
}
source_suffix = ['.rst', '.md']

# sphinx-jsを使用するための設定
js_source_path = '/root/src'        # jsソースのパス
jsdoc_config_path = './.jsdoc.json' # jsdocのconfigファイルのパス
extensions = [
    'sphinx.ext.autodoc',
    'sphinx_js'
]

# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

# The master toctree document.
master_doc = 'index'

# Usually you set "language" from the command line for these cases.
language = 'ja'
# directories to ignore when looking for source files.
exclude_patterns = []

# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'

# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False

# -- Options for HTML output ----------------------------------------------

# a list of builtin themes.
html_theme = 'alabaster'
html_static_path = ['_static']
```

```json:document_genarator/esdoc/.esdoc.json
{
  "source": "/root/src",
  "destination": "/root/build/api/esdoc"
}
```

```json:document_genarator/jsdoc/.jsdoc.json
{
    "tags": {
        "allowUnknownTags": true,
        "dictionaries": ["jsdoc"]
    },
    "source": {
        "include": ["/root/src", "package.json", "README.md"],
        "includePattern": ".js$",
        "excludePattern": "(node_modules/|docs)"
    },
    "plugins": [
        "plugins/markdown"
    ],
    "templates": {
        "cleverLinks": false,
        "monospaceLinks": true,
        "useLongnameInNav": false
    },
    "opts": {
        "destination": "./build/api/minami",
        "encoding": "utf8",
        "private": true,
        "recurse": true,
        "template": "./node_modules/minami"
    }
}
```

```docker:typedoc/Dockerfile
# docker-hubからnode入りコンテナを取得
# https://hub.docker.com/_/node/
FROM node

# コンテナ上の作業ディレクトリ作成
WORKDIR /my_typedoc

# 後で確認出来るようにpackage.jsonを作成
RUN npm init -y

# typescript doc
RUN npm i --save-dev typedoc

# typescript
RUN npm i --save-dev typescript
```

```json:typedoc/package.json
{
  "scripts": {
    "typedoc": "typedoc",
    "doc": "npm run typedoc -- --target es6 --moduleResolution node --ignoreCompilerErrors --out ./dist/ ./src/"
  }
}
```

```json:typedoc/tsconfig.json
{
    "compilerOptions": {
        "module": "commonjs",
        "target": "es6",
        "noImplicitAny": false,
        "sourceMap": false
    }
}
```

```rst:docs/index.rst
ドキュメントジェネレータテスト
=======================================

Contents:

.. toctree::
   :maxdepth: 1

   contents/esdoc
   contents/jsdoc
   contents/sphinx
   contents/jsdoc-sphinx/index
   contents/sphinx-js/index

Apiドキュメント
==================

* `Jsdoc APIドキュメント <../api/jsdoc/index.html>`_ 
* `Jsdoc - minami APIドキュメント <../api/minami/root/1.0.0/index.html>`_ 
* `Esdoc APIドキュメント <../api/esdoc/index.html>`_ 
* `Typedoc APIドキュメント <../api/typedoc/index.html>`_ 

索引
==================

* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`
```

```bash:bin/generate.sh
#!/bin/bash

# このシェルスクリプトのディレクトリの絶対パスを取得。
bin_dir=$(cd $(dirname $0) && pwd)

# jsdoc作成
cd $bin_dir/../ && docker-compose run documentation_generator jsdoc -d /root/build/api/jsdoc /root/src -r

# jsdoc作成 - minamiテンプレート
cd $bin_dir/../ && docker-compose run documentation_generator jsdoc -c /root/.jsdoc.json

# jsdoc作成 - jsdoc-sphinxテンプレート
cd $bin_dir/../ && docker-compose run documentation_generator jsdoc -t node_modules/jsdoc-sphinx/template -d /root/source/contents/jsdoc-sphinx /root/src -r

# esdoc作成
cd $bin_dir/../ && docker-compose run documentation_generator esdoc -c /root/.esdoc.json

# typedoc作成
cd $bin_dir/../ && docker-compose run documentation_generator_typedoc npm run doc

# sphinxドキュメント作成
cd $bin_dir/../ && docker-compose run documentation_generator make html
```

## 実行

generate.shでドキュメント作成後、`dist/docs/html/index.html`をひらいて確認できる。

## githubソース
今回試したソースは以下。

[github](https://github.com/hibohiboo/develop/tree/bb9a2e5f34ea3a490ad931da67ddd584727c26a2/tutorial/lesson/documentation_generator)

## 参考

[SphinxドキュメントをDockerでビルドする][*1]
[業務での利用事例Add Star][*2]
[PythonプロジェクトのドキュメントをSphinxで作成する][*3]
[プロジェクトを作る][*4]
[逆引き辞典][*5]
[ドメイン][*6]
[sphinx-js][*7]
[conf.py][*8]
[extension][*9]
[okikata][*10]
[拡張][*11]
[study 日本語解説][*12]
[jsdoc-sphinx][*13]
[github - jsdoc][**1]
[eclipse - jsdoc][**2]
[use jsdoc][**3]
[expressでのjsdoc][**4]
[jsdocをbootstrapできれいに整形する][*14]
[JSDoc使い方メモ][*15]
[wordpress js規約日本語訳][*16]
[Sphinx でドキュメントを作成して GitHub Pages で公開するまで][*17]
[Sphinx-Users.jp — Python製ドキュメンテーションビルダー、Sphinxの日本ユーザ会][*18]

[*1]:http://www.rhoboro.com/2016/09/04/docker-build-sphinx.html
[*2]:http://sphinx-users.jp/event/20101203_jus_benkyoukai/practical_sample/index.html
[*3]:http://qiita.com/icoxfog417/items/9e2eb932b61aa9b9e427
[*4]:http://sphinx-users.jp/gettingstarted/make_project.html#id2
[*5]:http://sphinx-users.jp/reverse-dict/index.html
[*6]:http://www.sphinx-doc.org/ja/stable/domains.html
[*7]:https://github.com/erikrose/sphinx-js
[*8]:http://www.sphinx-doc.org/ja/stable/config.html
[*9]:http://tk0miya.hatenablog.com/entry/20111206/p1
[*10]:http://oktavia.info/ja/pages/what/what.html
[*11]:http://sphinx.shibu.jp/extensions.html
[*12]:http://planset-study-sphinx.readthedocs.io/ja/latest/01.html
[*13]:https://github.com/HumanBrainProject/jsdoc-sphinx


[**1]:https://github.com/jsdoc3/jsdoc
[**2]:https://www.htmlhifive.com/conts/web/view/tutorial/jsdoc#HJSDoc5165529B66423001memberOf30BF30B0309281EA52D588DC5B8C3059308B65B96CD5
[**3]:http://usejsdoc.org/index.html
[**4]:http://stackoverflow.com/questions/31818538/jsdocs-documenting-node-js-express-routes

[*14]:https://blog.agektmr.com/2014/02/jsdocbootstrap.html
[*15]:http://qiita.com/opengl-8080/items/a36679f7926f4cac0a81
[*16]:https://wpdocs.osdn.jp/JavaScript_%E3%83%89%E3%82%AD%E3%83%A5%E3%83%A1%E3%83%B3%E3%83%88%E8%A6%8F%E7%B4%84
[*17]:http://qiita.com/key-amb/items/4f799fed51734987f3c5
[*18]:http://sphinx-users.jp/cookbook/hosting/