WordPressをMarkdownで執筆、あるいはMarkdown→HTML変換とGitHub Pagesの自動更新

2021年06月22日 火曜日


【この記事を書いた人】
坂口 和也

システムクラウド本部所属。IaaSサービスの画面を作ったりOSイメージをメンテナンスしたりしています。ゲレンデかサウナにいます。

「WordPressをMarkdownで執筆、あるいはMarkdown→HTML変換とGitHub Pagesの自動更新」のイメージ

はじめましての方ははじめまして、2020年のアドベントカレンダーをご覧になってくださった方はお久しぶりです、クラウド本部の坂口です。
私は普段、クラウドサービスのフロントエンド開発からOSイメージのメンテナンス、サービスの運用などをメインに行っています。

2020年12月にアドベントカレンダーで投稿した 我らの時代のコンテナデプロイ – Nomad, Consul, Vault はお楽しみいただけたでしょうか。
実はこの記事を執筆する際、様々な趣向を凝らしていました。今回はそれをご紹介いたします。

MarkdownとWordPress

エンジニアたるもの文章はMarkdownで書き、Gitでバージョン管理したいですよね。

しかしWordPressでMarkdownを利用するには、WordPress5.0のGutenbergエディタを使うかプラグインを導入する必要があります。
Gutenbergエディタは入力したMarkdown記法をリアルタイムでHTMLに変換するものですし、プラグインを選定するのも面倒です。

そこで私は、Markdownで文章を書きGitでバージョン管理しつつもそのコンテンツをWordPressに載せやすい方法を模索しました。
その結果、「Markdownを社内のGitHub Enterpriseにpushすれば、HTMLに変換してGitHub Pagesに掲載される」という方式に至ったのです。

GitHub Pages

GitHubには標準でGitHub Pagesという機能が備わっています。
これは、GitHubの特定のbranchを指定し、HTMLやCSS等のファイルを取得して静的に表示できる機能です。

まずは執筆用のRepositoryにあらかじめgh-pagesブランチを生やしておきましょう。
そしてRepositoryのSettingsから”GitHub Pages”を探し、Sourceに”gh-pages”ブランチを指定します。

これによって、gh-pagesブランチにpushされた静的ファイルをGitHub Pagesに表示することができるようになりました。

Github Pagesの自動更新

pushされたらGitHub Pagesを自動更新したいですよね。

社内で用意されており、GitHub Enterpriseとも連携しているDroneというCI/CDシステムを利用して自動更新を実現します。

まずはGitHubのアカウント設定からGitHub APIのためのアクセストークンを発行しておきます。
Droneと目的のRepositoryを紐付けておき、Droneの秘密情報としてアクセストークンをgithub_passwordなどと名前をつけて格納します。
最後に以下のような内容で.drone.ymlをRepositoryに追加しましょう。

pipeline:
  deploy:
    image: plugins/gh-pages
    environment:
      - DRONE_NETRC_MACHINE={GitHub Enterpriseのドメイン名}
    secrets: [ github_password ]
    username: "user"

このままpushすれば、Repositoryのdocsディレクトリの中身をgh-pagesブランチに自動でpushしてくれます。

Markdown -> HTML 変換

ここからは目的のMarkdownからHTMLへの変換を行います。

今回は変換ツールとしてpandocを使用します。
pandocは様々なフォーマットに対応する文章変換ツールで、Dockerイメージも存在するのでdroneで指定すればすぐに動かすことができます。

pipeline:
  build:
    image: pandoc/core
    commands:
      - 'pandoc -s index.md -o docs/index.html

.drone.ymlにこんな風に書いてみました。
push された index.md は pandoc により HTML に変換され、docs/index.html に出力されます。

上の設定でdocsディレクトリ配下は自動的にgh-pagesブランチにpushされるため、Markdownをpushすれば変換してGitHub Pagesで見れるようになりました。

Template編集

このままだと、GitHub Pagesのソースを見て、bodyタグ内をコピーしてWordPressに張り付けないといけません。
ページ下部に、bodyタグを抜き出してコピペをしやすくなるようなtextareaを設けたいと思います。

pandocはtemplateを読み込んでそれに従って変換を行ってくれるので、まずデフォルトのtemplateを出力します、
出力したtemplateはtemplate.htmlとでも名付けておきましょう。

次に、headタグ内に以下のようなscriptを追加します。
textareaタグを作成して、body.innerHTMLをvalueとしてbodyにappendChildするだけの単純なJavaScriptです。

<script type="text/javascript">
  window.onload = onLoad;
  function onLoad() {
    var element = document.createElement("textarea");
    element.value = document.body.innerHTML;
    element.style.width = '100%';
    element.style.height = '30em';
    document.body.appendChild(element);
  }
</script>

ここまで出来たら、作成したtemplate.htmlと一緒に以下のように編集した.drone.ymlをpushしてしまいましょう。
pipeline:
  build:
    image: pandoc/core
    commands:
      - 'pandoc -s index.md -o docs/index.html --template template.html'

commands部分を見るとわかる通り、今作ったtemplateを元にMarkdownからHTMLへの変換を行ってくれます。

GitHub Pagesを更新すれば、最下部にbodyタグ内を抜き出したtextareaが追加されると思います。

Lint

ここからは余談ですが、文章のチェックも行ってくれると嬉しいですよね。

textlintという文書校閲ツールを使ってこれを実現してみましょう。

pipeline:
  lint:
    image: node
    commands:
      - npm install textlint
      - npm install textlint-rule-preset-ja-technical-writing
      - $(npm bin)/textlint --format pretty-error --preset ja-technical-writing index.md

npmでtextlintと、技術文書チェックのプリセットをインストールした上で、index.mdをチェックします。
これにより、以下のようにDrone上で文書チェックを行うことができます。

「branchで書き、Lintのチェックが通らないとMasterにMergeできないようにする」といった応用もできそうですね。

Lint高速化

毎度npm installを書けているとチェックにかかる時間が長くなってしまいます。

今回は、npm installの成果物であるnode_modulesをキャッシュしてしまいましょう。
社内にはS3互換ストレージがあるので、マウントしてnpm_modulesをまるごと置いてしまいます。

pipeline:
  restore-caches:
    image: plugins/s3-cache:1
    endpoint: {S3ストレージのURL}
    access_key: {S3ストレージのアクセスキー}
    secret_key: {S3ストレージのシークレットキー}
    restore: true

linter-build:
  image: node
  commands:
    - npm install textlint
    - npm install textlint-rule-preset-ja-technical-writing

rebuild-cache:
  image: plugins/s3-cache:1
  settings:
    endpoint: {S3ストレージのURL}
    access_key: {S3ストレージのアクセスキー}
    secret_key: {S3ストレージのシークレットキー}
    rebuild: true
    mount:
      - node_modules

lint:
  image: node
  commands:
    - $(npm bin)/textlint --format pretty-error --preset ja-technical-writing index.md

こんな風に.drone.ymlを書くことで、初回npm install完了後はnode_modulesをキャッシュ、再度npm installする場合は手元にnode_modulesが存在するためインストール時間がとても短くなります。

完成

無事、以下の要件を満たすことができました。

  • Markdownで執筆
  • Gitでバージョンを管理
  • pushしたらMarkdownを校閲、HTMLに変換
  • 変換したHTMLをGitHub Pagesに自動公開
  • 公開されたページ下部にソースを表示

あとは、textareaに表示されているHTMLをWordPress標準エディタのHTML編集モードで貼り付けるだけです。

まとめ

今回はバージョン管理にGitHub、HTMLへの変換はpandoc、CI/CDはDroneを利用し、Markdownによる技術文書執筆環境を整えてみました。

同じような境遇の方がいらっしゃいましたら、是非お試しください。

坂口 和也

2021年06月22日 火曜日

システムクラウド本部所属。IaaSサービスの画面を作ったりOSイメージをメンテナンスしたりしています。ゲレンデかサウナにいます。

Related
関連記事