azukipochette's weblog

memory dump (mini)

PowerShell を使って Markdown を GitHub 風の HTML ファイルに変換する

TL;DR *1

PowerShell 6 以降で、下記のコマンドのように実行すればよい。

$mdfile = 'C:\path\to\yourmarkdownfile.md'
ConvertTo-Html -Body ('<div class="markdown-body">' + (ConvertFrom-Markdown -Path $mdfile).Html + '</div>')  -Head '<link rel="stylesheet" href="https://github.com/sindresorhus/github-markdown-css/blob/main/github-markdown.css">' | Out-File -FilePath out.html

おまけ (雑談)

皆さんは何でメモを書いているだろうか。私は最近もっぱら Markdown である。
Visual Studio Code は標準でプレビュー表示できるし、Pandoc によって MarkdownPowerPoint にも Word ファイルにもなる。
Pandoc は様々なドキュメントを相互に変換する非常に野心的なプロジェクトで、細かい部分で物足りないことも多いが大変便利なツールである。

pandoc.org

だが、実行環境の準備が 辛すぎる

私たちが望んでいることは単純明快である。Markdown ファイルを非エンジニアな人に見せて「拡張子 md って何のアプリで開くんですか?」とか「開いたら所々よく分からない文字が書いてあるんだけど」と言わわれずに、誰でも簡単に読めるファイルに変換したいのである。それなのに、HTML ファイルに変換するだけで、(Pandoc の場合) Haskell の環境整備が必要だったり、Markdown Parser なライブラリを使ったツールを作らなければならないなんて 辛すぎる

そんなある日、PowerShellMicrosoft Docs を眺めていたら、ConvertFrom-Markdown なるコマンドレットを見つけた。

docs.microsoft.com

しかも、このコマンドレットは PowerShell 6 以降で標準搭載されており、必要なときに気軽に変換できる *2

更に、この変換は内部的に Markdig という OSS ライブラリを使っているらしく、"Markdown" 仕様だけではなく "CommonMark" 仕様にも対応している。*3
なので、表や注釈といった表現もしっかり変換してくれる。

github.com

ConvertFrom-MarkdownHtml プロパティなどを持つオブジェクトを返すが、Html プロパティの中身は Markdown で記述された HTML タグだけを持っている。
最近の Web ブラウザはとても賢いので、そのまま不完全な HTML ファイルとして出力しても表示はできるが、正しい HTML ファイルとして出力するなら次のように記述することになる。

ConvertTo-Html -Body (ConvertFrom-Markdown -Path $mdfile).Html | Out-File -FilePath out.html

これで出力すると HTML ファイルにはなるが、見た目がシンプルすぎて物足りない。
開発者視点で最も見慣れている且つオシャレな Markdown の表示は GitHub だろうということで、GitHubMarkdownスタイルシートを使うことにする。

とはいっても、GitHub 社は直接 Markdown 用の CSS ファイルを提供していない。だが、同じことを思う人は既にたくさんいて、GitHubスタイルシートMarkdown 部分を抜いているリポジトリGitHub 上に公開されている。*4

github.com

このプロジェクトのファイルを直接参照してもよいが、表示は速いに越したことがないので CDN (Content Delivery Network) 上のファイルを使う。今回は Cloudflare 社が提供している cdnjs 上にあるファイルを使用する。

cdnjs.com

では、これをスタイルシートとしてヘッダーに追記すれば終わりか...と思うかもしれないがそうではない。
CSS の中身を見てみると、次のように記載されていることがわかる(一部のみ抜粋)。

.markdown-body details,
.markdown-body figcaption,
.markdown-body figure {
  display: block;
}

.markdown-body summary {
  display: list-item;
}

つまり、markdown-body クラスの範囲になければならない。 ということで、ConvertFrom-Markdown で変換した HTML タグを <div class="markdown-body></div> で囲む。
こうして完成したのが、最初に表示した以下のコードである。

$mdfile = 'C:\path\to\yourmarkdownfile.md'
ConvertTo-Html -Body ('<div class="markdown-body">' + (ConvertFrom-Markdown -Path $mdfile).Html + '</div>')  -Head '<link rel="stylesheet" href="https://github.com/sindresorhus/github-markdown-css/blob/main/github-markdown.css">' | Out-File -FilePath out.html

Enjoy!

*1:"Too Long Don't Read" の略で、「長すぎて読めないよ」 というが転じて「要約」として用いられている言葉らしい。

*2:PowerShell を入れなければならないじゃないか、というツッコミは私には聞こえない

*3: 私の記憶による歴史の話 : Markdown は かの John Gruber が作成したものでテキストで見やすくリッチな表現ができるので人気が出た。しかし John Gruber が作った仕様では表現力が物足りないと思ったものたちが「方言(Flavor)」として拡張し始めた。代表的なものに GitHub Flavored Markdown (GFM) がある。このように様々な方言ができたせいで、互換性に問題が出てしまい混乱した。そこで Markdown を標準化するために John Gruber に相談を持ちかけたが、John Gruber は自分が決めた仕様で十分だと取り合わなかったため、Markdown ではなく CommonMark として仕様をまとめたのである。つまり John Gruber 的には Markdown は彼が決めた Markdown であるが、私たちが知っている Markdown は CommonMark な部分も多分に含んでいるということである。曖昧な記憶なので、間違っていたら正解を教えてください。

*4:この記事を記述している時点で 5.8k スター...とんでもない需要だ