最高のソフトウェアドキュメント製作ツール(mkdocs + plantuml + mermaid.js)をdockerで作成する

## 1. はじめに

仕事で mkdocs を使うことがありました。
その際に、魅力的感じたので、自宅環境でも構築しました。

また、仕事では設定を変更することが無かったので知らなかったのですが、多くの便利な機能があり、合わせて紹介したいと思いました。

![sample](https://github.com/ryohei-takasugi/mkdocs-sample/blob/main/docs/docs/assets/img/readme/capture1.png?raw=true)

## 2. オススメポイント

### 2.1. 差分がわかりやすい
- テキストベースであるため、Githubで管理するときに変更の差分が分かりやすい。
  ソフトウェアドキュメントでは、仕様変更があった場所を探すことが容易であるべきです。
  ソースコードとセットでmkdocsを管理することで、コミットログから同じように変更点を把握することが可能です。

### 2.2. 見やすい
- markdownで記述した内容が、Webページとして表示するため、とても見やすくなる
- QiitaにもあるNote表記が使える
- 用語定義や注釈を記述できる
- コードブロックに行番号やハイライトをつけることができる

![code](https://github.com/ryohei-takasugi/mkdocs-sample/blob/main/docs/docs/assets/img/readme/capture2.png?raw=true)

### 2.3. 検索
- 日本語で文章全体を検索することができる
- 検索結果にハイライトをつけることができる

### 2.4. ダイアグラム
- デフォルトではないのですが、`plantUML`と`mermaid.js`を追加することができるため、多くの図をテキストベースで作成することができる。
- 画面イメージやネットワーク図は、テキストベースで作成できるものが無いため、`Visual Studio Code`の拡張機能である`Draw.io Integration`を利用する前提になります。

![uml](https://github.com/ryohei-takasugi/mkdocs-sample/blob/main/docs/docs/assets/img/readme/capture9.png?raw=true)

## 3. 導入

### 3.1. コンテナの作成

私の環境は、次のファイルを作成して、構築しました。
ファイルを作成後、`docker-compose up -d` を実行しました。
`docker-compose.yml`の
```
source: "./"              # docker-compose.ymlがあるホストディレクトリ直下と
target: "/root/projects"  # コンテナディレクトリの /root/projects をファイル共有のような状態でつなぐ
```
は、人により求めるディレクトリが異なると思いますので、変更してから使ってください。


``` :フォルダ構造
+ folder
  + docker-compose.yml
  + Dockerfile
```

``` yml: docker-compose.yml
version: "3"

services:
  app:
    container_name: mkdocs
    build:
      context: .
      dockerfile: Dockerfile
    tty: true
    stdin_open: true
    ports:
      - "127.0.0.1:18000:18000"
    depends_on:
      - plantuml
    volumes:
      - type: bind
        source: "./"
        target: "/root/projects"
  plantuml:
    container_name: plantuml-server
    image: plantuml/plantuml-server:jetty
    restart: always
```

``` Dockerfile:Dockerfile
FROM alpine:3.12

RUN apk update \
  && apk add --no-cache gcc libc-dev python3 py3-pip python3-dev \
  && pip3 install --upgrade pip \
  && pip3 install mkdocs mkdocs-material plantuml-markdown python-markdown-math pygments pymdown-extensions

RUN mkdir -p /root/projects
```

### 3.2. mkdocsの設定
私の環境では次のように設定しています。
かなりたくさんの設定を入れたたため、必要なところだけ抜き出すか、とりあえずコピペで使ってもらえたらと思います。

``` yml:mkdocs.yml
site_name: My Docs
# [テーマ]
theme:
  name: material
  # ロゴ
  logo: assets/img/icon/icon.svg
  # サイトの言語
  language: ja
  font:
    # 通常のフォント
    text: Roboto
    # codeの等幅フォント設定
    code: Roboto Mono
  features:
    # ページナビゲーションを折りたたみ可能なリンクで左側に配置します。
    - navigation.expand
    # トップへ戻るボタン
    - navigation.top
    # スクロールしたときヘッダーを自動的に非表示にする
    - header.autohide
    # 検索の候補リスト表示を表示する
    - search.suggest
    # 検索で一致した結果をハイライトする
    - search.highlight
    # コンテンツタブ表示を有効にする
    - content.tabs.link
  # ダークモードスイッチ
  palette:
    - media: "(prefers-color-scheme: light)" 
      scheme: default
      toggle:
        icon: material/toggle-switch-off-outline
        name: Switch to dark mode
    - media: "(prefers-color-scheme: dark)" 
      scheme: slate
      toggle:
        icon: material/toggle-switch
        name: Switch to light mode
# [プラグイン]
plugins:
  # 検索機能
  - search:
      lang: ja
      # インデックス対象の条件
      separator: '[\s\-\.]'
      # 各ページのタイトル、セクション見出し、および全文にインデックスを付けます。
      indexing: 'full'
# [拡張機能]
markdown_extensions:
    # 目次
    - toc:
        # 自動生成を有効にする
        permalink: true
        # 目次の上に表示する文言
        title: 見出し
        # 見出しにする深さ
        toc_depth: 3
    # コードハイライトの設定（デフォルトのcodehiliteを使わずに拡張機能を使用）
    - pymdownx.highlight:
        # (auto_titleなどの他の機能を有効にするためtrue)
        use_pygments: true
        # タイトルが設定されていないと自動的に言語名を表示する
        auto_title: true
        # 行番号を表示する
        linenums: true
        # 行を選択できアンカーリンクを生成可能にする
        anchor_linenums: true
    # コードハイライトの設定(インラインブロック版)
    - pymdownx.inlinehilite
    # アラート修飾(Note修飾)を有効化
    - admonition
    # コンテンツの折りたたみを有効化
    - pymdownx.details
    # 打ち消し線の追加
    - pymdownx.tilde
    # 下付き文字と上付き文字の追加（tilde拡張も必要）
    - pymdownx.caret
    # テキストの強調表示が可能になる（tilde,caret拡張も必要）
    - pymdownx.mark
    # ドキュメント内の追加、削除、または更新されたセクションを強調表示
    - pymdownx.critic
    # キーボードアイコンの追加
    - pymdownx.keys
    # 略語
    - abbr
    # 参照
    - attr_list
    # HTML内にMarkdownを記述できる
    - md_in_html
    # 注釈の追加
    - footnotes
    # 定義リスト
    - def_list
    # タスクのチェックリストを追加
    - pymdownx.tasklist:
        custom_checkbox: true
    # グリッド表示の有効化
    - tables
    # 任意のファイルのコンテンツを他のドキュメントやソースファイルを含むドキュメントに埋め込む機能
    - pymdownx.snippets
    # コンテンツタブ表示の有効化
    - pymdownx.tabbed:
        alternate_style: true 
    # PlantUMLの表示設定
    - plantuml_markdown:
        server: http://plantuml:8080
        format: svg
    # mermaidの表示設定
    - pymdownx.superfences:
        custom_fences:
            - name: mermaid
              class: mermaid
              format: !!python/name:pymdownx.superfences.fence_code_format
    # 絵文字
    - pymdownx.emoji:
        emoji_index: !!python/name:materialx.emoji.twemoji 
        emoji_generator: !!python/name:materialx.emoji.to_svg
# [カスタムCSS]
extra_css:
  - assets/css/extra.css
# [カスタムJS]
extra_javascript:
  - assets/js/extra.js
# [mkdocsの拡張]
extra:
  # このサイトのバージョン
  version: 1.0
  # フッターのソーシャルリンク
  social:
    - icon: fontawesome/brands/twitter
      link: https://twitter.com/ryohei_takasugi
      name: ryohei_takasugi on Twitter
    - icon: fontawesome/brands/github
      link: https://github.com/ryohei-takasugi
      name: ryohei_takasugi on Github
# [フッター] 著作権表示
copyright: Copyright &copy; 2020 - 2022 ryohei_takasugi
# [ページナビゲーション]
nav:
  - 区切り１:
    - はじめに: index.md
    - Note記法: section/page-1.md
    - UML: section/uml.md
    - コード: section/code.md
    - リスト: section/list.md
    - 注釈: section/footnotes.md
    - 取り消し線など: section/formatting.md
    - 表: section/grid.md
  - 区切り２:
    - section_page2.md
    - 画像サンプル: section/section2-1.md
# ローカル環境で表示する場合はfalse、Webサーバー経由ならTrue
use_directory_urls: false
# 公開するページのPort番号を指定
dev_addr: '0.0.0.0:18000'
```

## 4. 使い方

### 4.1. ファイル配置

導入で紹介した `docker-compose` は、各アプリケーションのプロジェクトフォルダに入れるイメージです。
フォルダ構造としては、次のようになります。

```
project-folder
  + app     # 開発中のプロジェクトフォルダ(railsなど)
  + config  # 開発中のプロジェクトフォルダ(railsなど)
  + log     # 開発中のプロジェクトフォルダ(railsなど)
  + ...
  + ...
  + shell
    + new.sh
    + build.sh
    + serve.sh
  + docs
      + docs
          + assets
              + img
              + js
              + css
          + section
      + includes
      + site
      mkdocs.yml
  docker-compose.yml
  Dockerfile
```

### 4.2. コマンドの実行

mkdocsのコマンドは「serve, build」あたりをよく使うことになります。

#### 4.2.1. コンテナ内での実行
VScode拡張機能`Remote - containers`のリモートエクスプローラーから、対象のコンテナを右クリックして、WindowAttachを行います。
新しいVScodeが起動したら、新しいターミナルを起動して、`mkdocs serve`や`mkdocs build`を実行します。

#### 4.2.2. コンテナ外からの実行
次のコマンドを実行します。

```shell:build.sh
docker exec -i mkdocs /bin/ash -c "cd /root/projects/docs && /usr/bin/mkdocs build"
```

```shell:serve.sh
docker exec -i mkdocs /bin/ash -c "cd /root/projects/docs && /usr/bin/mkdocs serve"
```

### 4.3. markdown便利拡張

markdown を編集するに便利な入力補完は、`Visual Studio Code` で `Markdown All in One` を導入して対応しています。
特に見出し番号の自動変更が便利です。


## 5. 参考サイト
- [mkdocs公式](https://www.mkdocs.org/)
- [mkdocs-material公式](https://squidfunk.github.io/mkdocs-material/)