TypeScript: API-Extractor(tsdoc) で markdown を生成し、それを Word に変換して簡易仕様書へ

# 背景
TypeScript でコメントを元に Word か PDF を生成して仕様書にしようとした際の記録

今回は tag 拡張もしないし、Word も適当でよいので設定も変換したら OK ってとこがゴール


# 環境
- windows 10
- node.js v18.11.0
    - nvm 1.1.10
    - npm 8.19.2
- office(word): *.docx 出力用

# 結論
1. [API-Extractor(tsdoc) + API-Documenter で markdown を生成](#api-extractortsdoc--api-documenter-で-markdown-を生成) 
    - マークダウンはこんな感じ<br> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/ad3a35a1-f871-8a2b-7467-3640c38404c4.png)

1. [pandoc で markdown ファイル群を結合して Word を生成](#pandoc-で-markdown-ファイル群を結合して-word-を生成)
    - Word イメージ<br>![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/a3c8b7e5-d202-9d4e-d1f1-a36714de5c3e.png)

# 詳細
## API-Extractor(tsdoc) + API-Documenter で markdown を生成
まずは API-Extractor で API Model の生成後、
API-Documenter で markdown 生成まで
### Api-Extractor (tsdoc)
#### API-Extractor をインストールして初期化と設定
まずはインストール
```powershell: install
npm install -g @microsoft/api-extractor
```
初期化して、api-extractor.json を生成
```powershell: init して、api-extractor.json を生成
api-extractor init
```

api-extractor.json の最低限の設定は、"mainEntryPointFilePath" 
tsconfig.json での outDir を元に設定すればよいかと。

```json: api-extractor.json の変更点
  "mainEntryPointFilePath": "<projectFolder>/built/index.d.ts",
```
上記の例では、tsconfig.json で以下のように設定してる為

```json: tsconfig.json
"outDir": "./built/",      /* Specify an output folder for all emitted files. */
```

#### tsconfig の設定変更
Model 解析をする為に必要な *.d.ts の生成をする為に以下を有効化

```json: 設定変更
    "composite": true,　　// declarationMap に必要
    "declaration": true
    "declarationMap": true
```

変更後に、tsc で build が必要

> tsc

:::note warn
Build しないと、設定変更だけなので、以下のようにエラーが出る筈
> The "mainEntryPointFilePath" path does not exist: 
:::

#### モデルの生成前準備
apiReport の出力先変更
```json: api-extractor.json 変更結果はこんな感じ。コメント外して、json エラーを解除（"," 追加）した程度
  "apiReport": {
    "enabled": true,
    "reportFileName": "<unscopedPackageName>.api.md",
    "reportFolder": "<projectFolder>/temp/",
    "reportTempFolder": "<projectFolder>/temp/",
  },
```

:::note info
コメント内の default の出力先は <code>\<temp\></code> としてるが、間違っていて、実際は <code>\<etc\></code> になっている。
:::

:::note warn これを
故に、上記をしないと、以下エラーが出ます。
> Error: Unable to create the API report file. Please make sure the target folder exists:

回避策として、以下でもOKかと
<code>\<projectFolder>/etc</code> フォルダを生成
:::

#### で、ようやくAPI Model を生成
*.api.json を生成
```powershell: API モデルを生成
api-extractor run --local --verbose
```

この時点で、以下が生成されていれば OK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/7c420893-a146-5109-7645-15accdd327ff.png)

### api-documenter
#### api-documenter のインストール

```powershell: api-documenter のインストール
npm install -g @microsoft/api-documenter
```

#### api-documenter での markdown 生成
```powershell: markdown 生成
api-documenter markdown -i ./temp   
```
:::note info
入力フォルダ(-i) <code>./temp</code> は [api-extractor.json](#モデルの生成前準備) 設定次第
:::

最終的な markdown の出力例はこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6d4b1297-9ee4-208b-3b85-c0cebe25aa20.png "markdown 出力例")

## pandoc で markdown ファイル群を結合して Word を生成

### まずは install 
ダウンロードは以下から最新版を

https://pandoc.org/installing.html

### pandoc で出力

面倒なので、power shell ファイルを用意して
> ./createWord.ps1 

みたいな感じで生成する

```powershell: createdWord.ps1
Set-Location ./doc/markdown

# markdown ファイルの一覧
$inputs = Get-ChildItem ./ -Recurse -Name -include *.md | Sort-Object -Descending
# ファイル名: 拡張子で勝手に出力内容を変えてくれる。但し、対応機能のインストールは必要な可能性有。-f/-t は削除した場合
$output = "../word/Specifications.docx"

# 以下 {user} を自身の user へ
C:\Users\{user}\AppData\Local\Pandoc\pandoc.exe `
  --toc `
  -f markdown `
  -N $inputs `
  -t docx `
  -o $output

Set-Location ../../

# --reference-doc=*.odt # *.odt を提供することで好みのスタイルへ
```
概要としては以下
1. *.md フォルダに移動
1. ファイル一覧取得
1. -N オプションで渡して -o で出力フォルダを渡す
1. pandoc を呼び出して、markdown to word を実行
1. フォルダを元に戻す

こんな感じで出力されれば完成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/791adfce-6f5e-fd9c-7f20-ee6f08b1959a.png "word 生成例")

pandoc についてはいろいろ情報があるので、割愛

# ちょっとした tips
## package.json の scripts 設定例
こんな感じで設定して、設定して、<code>npm run apidoc</code> ってやれば、build して markdown が生成される筈
```json: package.json への追加
"scripts": {
    "preapidoc": "tsc --build",
    "apidoc": "api-extractor run --local --verbose && api-documenter markdown -i ./temp -o ./doc/markdown",
}
```

### npm run apidoc の前後に何かを作業するって便利
package.json 内の scripts に pre{script name}, post{script name} を記述する。
詳細は以下。[実例は上述](#packagejson-の-scripts-設定例)

https://docs.npmjs.com/cli/v6/using-npm/scripts

## 複数の package をまとめる
api-documenter の input フォルダに *.api.json/md を並べておけば、全部まとめて markdown にして package 一覧に入れてくれる。

こんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9e7a92ca-f221-84ba-e1ad-35eb5fb12b09.png "複数の package をまとめた例")

## api-extractor では markdown/yaml が生成可能

## pandoc で pdf や HTML 等出力可能

# 参照
コードからモデルを生成

https://api-extractor.com/

定義

https://tsdoc.org/

https://github.com/microsoft/tsdoc/

pandoc 

https://pandoc-doc-ja.readthedocs.io/ja/latest/users-guide.html

# あとがき
当初は jsdoc を試してて、途中で typedoc に気付いて試行してたけど、
結局 tsdoc を利用したくて api-extractor にしました。

決めては、TypeScript を生み出した Microsoft が推してるってところ。

以下の記事にあるように、自分も JavaScript は苦手だったけど、やってみたら C# が好きだった感覚と似てた

https://learn.microsoft.com/ja-jp/archive/msdn-magazine/2013/january/javascript-typescript-making-net-developers-comfortable-with-javascript

この辺とかにも

> C# と同様、TypeScript には にジェネリックやラムダ式 (またはそれらに等価なもの) があります。

https://learn.microsoft.com/ja-jp/archive/msdn-magazine/2015/january/typescript-understanding-typescript
 
typedoc もよかったんだけどねぇ

## typedoc もいいよね
使いやすいし、検索窓がめっちゃ便利なので、HTML で良い時に使いたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/6787a259-b9f0-39ed-1ac9-fb01797be961.png)