🌊

GitHubのREADME.mdをイイ感じにHTMLに変換してプッシュする

2024/09/03に公開

概要

社内向けのツールをGitHubで開発した際にREADME.mdにマニュアルを書いていたのですが、GitHubのアカウントを持っていない人にもマニュアルを配布しやすくするため、README.mdをイイ感じの見た目のHTMLに変換してリポジトリにプッシュすることにしました。

この記事では、その方法についてまとめます。

実現したいこと

今回実現したいことに関わる要件は以下の通りです:

  • GitHub上のプレビューと同じように、スタイルやシンタックスハイライトが効いた見た目にする
  • スタイルや画像をすべて埋め込んで、単独のHTMLファイルとして配布できるようにする
  • プルリクがmasterブランチにマージされた後にHTMLに変換し、masterにプッシュする
    • ただし、masterはGitHub Repository rulesetsで保護されている

結果

先に結果を示すと、つぎのような見た目のHTMLが生成されるようになります:

(これはnmoa/markdown-html-exampleのREADME.mdを変換したものです)

実現した手順は以下のとおりです:

  1. markdown-to-html-cliを使用してREADME.mdをHTMLに変換する
  2. create-pull-requestを使用して作成したHTMLをプッシュし、プルリクエストを作成する
  3. GitHub CLIのgh pr mergeコマンドでプルリクを自動マージする

実際のGitHub Actionsの.ymlファイルは以下のようになりました。

name: Generate README.html

on:
  push:
    branches:
      - master
    paths:
      - README.md

permissions:
  contents: write
  pull-requests: write

jobs:
  convert:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v4

      - name: Set up Node.js
        uses: actions/setup-node@v3

      - name: Install dependencies
        run: npm i -g markdown-to-html-cli

      - name: Convert .md to .html
        run: markdown-to-html --source README.md --output README.html --title title --img-base64 --no-dark-mode

      - name: Create Pull Request
        id: cpr
        uses: peter-evans/create-pull-request@v6.1.0
        with:
          commit-message: "[bot] Update README.html"
          title: "[bot] Update README.html"
          body: "Automated update of README.html from README.md by [create-pull-request](https://github.com/peter-evans/create-pull-request) GitHub action"
          labels: github-actions
          delete-branch: true

      - name: Merge Pull Request
        if: steps.cpr.outputs.pull-request-operation == 'created'
        run: gh pr merge --merge --auto ${{ steps.cpr.outputs.pull-request-number }}
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

解説

なぜこの方法を選択したのか、それぞれ解説していきます。

トリガー

on: push: branches: masterだけだとプルリクの自動マージによって再度ワークフローが実行されて無限ループになるのが怖かったのと、無駄にActionsを走らせないようにするために、paths: README.mdを指定しています。
ただし、こちらの情報によるとGITHUB_TOKENを使用したイベントはトリガーの対象にならないようなので、無限ループは起こらなさそうです。

Markdown→HTML変換

細かい設定をしなくても以下の2つの要件を満たすことができるツールとしてmarkdown-to-html-cliが最適でした:

  1. GitHub上のプレビューと同じように、スタイルやシンタックスハイライトが効いた見た目にする
  2. スタイルや画像をすべて埋め込んで、単独のHTMLファイルとして配布できるようにする

1については特にオプションを指定せずに対応でき、2については--img-base64オプションを指定することで画像を埋め込むことができます。

ただし、markdown-to-html-cliはGitHub Actionsでも使用可能ですが、執筆時点のv4.1.0ではActionsに--img-base64に相当するオプションがなかったため、npm installして実行する形にしています。

pandocを使用していない理由

MarkdownからHTMLに変換するツールとしてはpandocも有名です。また、GitHubのスタイルを実現するカスタムCSSとしてgithub-markdown-cssもあり、以下のようなコマンドでスタンドアロンなHTMLを生成できるため、最初はこれを検討していました。

pandoc -f gfm -t html5 --embed-resources --standalone -c https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.6.1/github-markdown.css README.md -o README.html

しかし、以下の問題がありました:

  • シンタックスハイライト以外のスタイルが適用されない
  • 箇条書きの内部に作成したテーブルが正しくレンダリングされない

具体的には、以下のような見た目のHTMLとなってしまいました。

これらの理由から、markdown-to-html-cliを使用することにしました。

プルリクエスト作成

masterブランチはGitHub Repository rulesetsで直接のプッシュを禁止していたため、プルリクエストを作成して自動でマージすることにしました。
Deploy Keysを作成してGitHub Repository rulesetsのBypass listに追加することで直接のプッシュも可能だったかもしれませんが、このためだけにDeploy Keysを作成する必要はないと判断し、この方法を選択しました。

プルリクの作成にはcreate-pull-requestアクションを使用しました。
labels: github-actionsでPRにラベルを付与することで、自動生成したプルリクを識別しやすくしています。

プルリクエストの自動マージ

GitHub ActionsのワークフローではデフォルトでGitHub CLIが使用可能なため、gh pr mergeコマンドで自動マージする形としました。
プルリク作成のステップでid: cprを指定しているため、${{ steps.cpr.outputs.pull-request-number }}でプルリクの番号を取得可能になっています。

まとめ

GitHubのREADME.mdをイイ感じにHTMLに変換してプッシュする方法についてまとめました。

様々な実現方法があると思いますが、意外とこの手順を紹介している記事は見つからなかったため、同じようなことを実現したい方の参考になれば幸いです。
nmoa/markdown-html-exampleのリポジトリも参考にしてみてください。

GitHubで編集を提案

Discussion