Elm
elm-doc
ElmDay 25

Elmの「あの感じ」のドキュメントを社内スコープで展開してみます

Elm Advent Calendar2017、今年は去年よりも大いに盛り上がっていて、沢山の人達が沢山の情報を上げていて、毎日楽しく拝見しております。
それでは最終日、行かせて頂きます。

社内向けドキュメントの展開

ワタクシの務めるFringe81ではElmを用いたプロダクトが現在2つ稼働しています。
3つめ4つめも仕込んでいくような気配もあるので、徐々に社内共通で使うライブラリも作り出したりするようになってきました。
さて、このライブラリ、仮にElm Packagesで一般向けに公開しようとなるとあらゆる人に使いやすく設計する必要があるため、グッと敷居が高くなるんですが、プロダクト開発速度を考えると結構な労力を使って一般化レベルに持っていくまでの余裕は無かったり。
という事で、社内最適化を考えたときに、社内スコープでドキュメントを参照してもらいたいという欲求に対する1つのパターンを提示できればなーと思います。
さらにドキュメントはElm Packagesの体裁で一貫性を持たせていこうと思います(カッコイイですよね♪)。

スクリーンショット 2017-12-24 16.53.36.png

全体の流れ

ステップとしては下記のような感じです

ソースコードにコメント書く 
  -> ソースコメントからドキュメントファイルを生成 
  -> テスト表示 
  -> ドキュメントサイト構築 
  -> 公開/展開

ドキュメントの記述

ドキュメンテーションフォーマットに関しては公式ガイドがあります。まずテキトーに作ったアプリケーションをもとに、このガイドに沿ってコメントを付けていきたいと思います。

モジュールが複数あったほうが応用が聞くと思うので、Main.elmと、モデルの知識をカプセル化したTypes/Model.elmの2モジュールを作ってみます。

Main.elm
module Main exposing (Msg, init, main, update, view)

{-| This application offers transforming a model into gained or losing.

# Definition
@docs Msg

# Determine a next model.
@docs init, update

# Create view
@docs view

# Entry point
@docs main
-}

import Html exposing (Html, button, div, span, text)
import Html.Events exposing (onClick)
import Types.Model as Model exposing (Model)


{-| All of action of this Application.
-}
type Msg
    = Gain
    | Lose


{-| Initial model and effects.
-}
init : ( Model, Cmd Msg )
init =
    ( Model.initial, Cmd.none )


{-| Updating model and generating effects.
-}
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        Gain ->
            ( Model.gain model, Cmd.none )

        Lose ->
            ( Model.lose model, Cmd.none )


{-| Create views of this application.
-}
view : Model -> Html Msg
view model =
    div []
        [ button [ onClick Lose ] [ text "lose" ]
        , span [] [ text <| toString model ]
        , button [ onClick Gain ] [ text "gain" ]
        ]


{-| The entry point of this application.
-}
main : Program Never Model Msg
main =
    Html.program
        { view = view
        , init = init
        , update = update
        , subscriptions = always Sub.none
        }
Types/Model.elm
module Types.Model exposing (Model, gain, initial, lose)

{-| This module have a knowledge of model.
For example, a initial state and a way of how to change it.

# Definition
@docs Model

# Initial Model
@docs initial

# Changing Model
@docs gain, lose
-}


{-| Type of model.
-}
type alias Model =
    Int


{-| Initial model.
-}
initial : Model
initial =
    0


{-| Change a model to gained form.
-}
gain : Model -> Model
gain m =
    m + 1


{-| Change a model to lost form.
-}
lose : Model -> Model
lose m =
    m - 1

ドキュメントファイル生成+簡易閲覧

Elm Packagesのドキュメントは専用のJSONフォーマットを読み込んで生成される模様。
準備としてelm-package.jsonsummaryにプロジェクト概要、exposed-modulesに下記のようにドキュメント化したいモジュールを記述します。

{
  ...
  "summary": "Sample Application",
  ...
  "exposed-modules": [ "Main", "Types.Model" ],
  ...
}

そしてコンソールを開いたらプロジェクトルート上で下記コマンドを流します。

elm-make --docs=documentation.json

これでdocumentation.jsonが生成されたと思います。
このファイルを公式のドキュメントプレビューガイドで開いてみましょう。

スクリーンショット 2017-12-24 15.53.33.png

でました!おなじみの「あの感じ」で。
一応、会社内のElmer達に向けてこのページを開いてJSONファイル食わせてくれー、とお願いする運用も可能ではあるんですが、リロードすると消えちゃいますし、使い勝手が悪い!ということでもう少し運用し易い形に持っていきたいと思います。

elm-docでドキュメントサイトを構築

elm-docさんを使うことで、一時的ではなくドキュメントサイトのブツを残すことが出来ます。なんて素晴らしいライブラリ!
利用者から見た簡易構築手順もサラッと残しておきます。

Python環境の構築

elm-docはPythonを利用するようなのでまずは下記を準備します。ワタクシはpyenvを使って3.4.3にしました。

  • pythonのバージョンを3.4以上に上げる
  • python-magicをインストール

elm-docのインストール

pip install --upgrade pip setuptools
pip install elm-doc

elm-docでドキュメントサイトをビルド

elm-docのREADME.mdを読めば、ファイル除外など色々とオプションがありますが、今回はスタンダードに。
プロジェクトルートで下記を実行します。

elm-doc . --output docs

これでdocsというディレクトリ、配下にファイル群が生成されると思います。

閲覧環境を構築

このdocsディレクトリを社内サーバーで公開すれば完了でございます。
ただ、社内ライブラリということで、社内のElmersがカスタマイズしてプルリクしてくれるというシナリオも想定して、ローカルでの最新のドキュメントを参照しやすい方法も構築します。
今回は、openernode-web-serverを使います。
まずはインストール。

npm i -D opener node-web-server

次に、プロジェクトルートにサーバーの設定ファイルを生成します。

server.conf
{
  "host"       : "localhost",
  "port"       : 4000,
  "docRoot"    : "docs",
  "allowUnknownMIMEType": true,
  "MIME" : {
    "": "text/html"
  }
}

package.jsonにスクリプトを設定します。ポートは4000としてみます。

{
  ...
  "scripts": {
    "doc": "./node_modules/.bin/opener http://localhost:4000 && ./node_modules/.bin/nws -c server.conf"
  },
  ...
}

これでブラウザが開いてドキュメントサイトを表示されます。

npm run doc

ドキュメントを見てみる

ではブラウザ上で、「あの感じ」で生成されたファイルを閲覧していきたいと思います。

サイトのルート

docs/index.htmlはプロジェクトのドキュメントリンクと共に、依存パッケージのドキュメントも包含してくれます。
今回、user/projectという名前になっているのはelm-package.jsonrepositoryのURLの記述のためです。
本来、githubのURLを入れるんですが、ウチはgitlabを使っているので、そのままにしています。

スクリーンショット 2017-12-24 16.23.56.png

プロジェクトのルート

プロジェクト直下のREADME.mdの内容が表示されます。
右側のリンクでモジュールのドキュメントにアクセス出来ます。

スクリーンショット 2017-12-24 16.51.44.png

モジュールページ

見慣れたページの感じになっています。これで社内Elmer達がお仕事をしやすくなってくれると嬉しい!

スクリーンショット 2017-12-24 16.53.36.png

今回は以上でございます。
この仕組みが使いやすいのか否かはまだ検証フェーズで御座います(笑)。
それでは皆様、良いお年を!