Markdownからhtmlファイルを生成してアプリのヘルプファイルとして表示する

# 概要

アプリにヘルプファイルがあるとユーザーにとっては便利です。
他にも以下のような条件を満たしたいです。

- ヘルプファイルは今どきにhtmlファイルで
- オフラインでも動作するようにローカルファイルとしてアプリに同梱
- アプリからワンクリックで開きたい
- ヘルプの内容はMarkdownで書きたい
- Markdownが更新されたら自動でHtmlファイルに変換してアプリに組み込みたい

そこでMarkdownでヘルプを書いて、変換したローカルhtmlファイルをアプリに組み込み、ヘルプファイルとして使用する方法を説明します。

サンプルはWPFで書きましたが、WinFormsでもUWPでも同じようにできます。

# スクリーンショット

こんなアプリがあったとして、どうやって使うのか？という時に、中央の<kbd>HELP!!</kbd>ボタンを押すと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120077/d6b241e9-7cd2-79c4-8176-ebf2e60c79d0.png)

ローカルHTMLファイルが呼び出され、ヘルプがブラウザで表示されます。
これで中央の<kbd>🍪</kbd>を押せばクッキーが焼けることが分かります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120077/f867bc2d-2c90-c26c-d56e-639e96a6c84d.png)

# やり方

## Markdownを書く
ヘルプファイルの元となるMarkdownを好きなエディタで書きます。私はTyporaを愛用しています。

Markdownの先頭部分に タイトル・著者名・日時を書くとhtmlファイルのHeadに反映されます。

```md
% Help Coockie Creater
% soi
% 2021/02/11

# 🍪HOW TO USE🍪

丸いところをクリックすると<kbd>Coockie Count</kbd>が1つ増えます。

## UI説明

| 項目           | 見た目   | 説明                       |
| -------------- | -------- | -------------------------- |
| Coockie Count  | 文字     | 現在の焼けたクッキー数     |
| Coockie Button | クッキー | 押すとクッキーが焼き上がる |

# 🍪ホームページ🍪

Githubで公開しています！

[Coockie Creater](https://github.com/soi013/HelpHtmlTest)

```

## PandocでHtmlファイルへ

Pandocをインストールします。
ToCの付いたテンプレートとGithub風のcssを指定して、単一htmlファイルを生成します。

```powershell
pandoc -s ./help.md -o ./help.html --toc --template=./elegant_bootstrap_menu.html --self-contained -t html5 -c my_markdown.css
```

詳しくは以下のリンクを参照ください。

[pandocでmarkdownを1ファイルのhtmlに変換する - chocolattips](https://chocolattips.hatenablog.com/entry/2020/10/23/000000)
[Pandocメモ - jou4のブログ](http://jou4.hateblo.jp/entry/2013/03/04/215020)

## PowerShell
ビルド**前**イベントでPowerShellスクリプトを呼び出し、pandocでhtmlファイルへの変換を行います。
ビルド**前**なのは生成したhtmlファイルをアプリのコンテンツファイルとして組み込むためです。
pandocの作業は結構時間がかかるため、ビルドのたびに動かしたくありません。そこでMarkdownファイルとhtmlファイルの更新日時を比較して、必要な場合だけ生成するようにします。

```powershell
cd 'Help'
$sourcePath = ".\help.md"
$sourceTime = $(Get-ItemProperty $sourcePath).LastWriteTime
$targetPath = "..\Resources\help.html"
if (Test-Path $targetPath)
{
    $targetTime = $(Get-ItemProperty $targetPath).LastWriteTime
}
else
{
    $targetTime = 0
}

echo "Creation help.html: sourceTime is $sourceTime, targetTime is $targetTime"

# 生成したHTMLファイルが元のMarkdownファイルより更新日時が新しいときのみコンバートする
if ( $sourceTime -gt   $targetTime )
{
    echo "Start Create help.html"
    # Pandocを使用してMarkdownからHTMLファイルを生成する。cssなどを指定する
    & 'C:\Program Files\Pandoc\pandoc' -s ./help.md -o ../Resources/help.html --toc --template=./elegant_bootstrap_menu.html --self-contained -t html5 -c my_markdown.css
    echo "Finished Create help.html"
}
```

ビルド前イベントでPowerShellスクリプトを呼びます

```xml:csproj
  <Target Name="PreBuild" BeforeTargets="PreBuildEvent">
    <Exec Command="powershell -ExecutionPolicy Unrestricted &quot;$(ProjectDir)\Help\CreateHtmlPandoc.ps1&quot;" />
  </Target>
```

## htmlファイルのプロパティ
PowerShellが出来た時点で一度ビルドします。するとプロジェクト＞Resourcesフォルダにhtmlファイルが生成されます。
VisualStudio上でこれのプロパティを`コンテンツ`、`新しい場合はコピーする`にしておきます。
またコード管理を使用している場合は生成したhtmlファイルは管理対象から除外しておきます。
ここでもう一度ビルドすると実行フォルダにResourcesフォルダができ、その中にhtmlファイルが配置されます。

## ローカルhtmlファイル呼び出し

アプリから、上記で生成して実行フォルダに配置されたhtmlファイルを呼び出します。
これでブラウザでhtmlファイルが表示されます。

```csharp
private void Button_HelpClick(object sender, RoutedEventArgs e)
{
    string htmlFilePath = "Resources/help.html";
    var pi = new ProcessStartInfo("cmd", $"/c start {htmlFilePath}") { CreateNoWindow = true };
    Process.Start(pi)?.WaitForExit();
}
```

# 全体コード

全体コードを以下の場所においておきます。
https://github.com/soi013/HelpHtmlTest

# 環境
VisualStudio 2019 Version 16.8.4
.NET 5
C# 9
PowerShell Version 5.1.19041.610