📔

技術書典12で用いた同人誌の執筆環境とGitHub Oriented Writingの紹介

2022/02/04に公開

はじめに

TL;DR

  • 同人誌の執筆には Re:VIEW を用い、textlint や prh といったツールを導入した
  • GitHub Actions による CI/CD で Lint や本のビルド、Discord への通知などを導入した
  • GitHub Oriented Writing とは GitHub に執筆に関する情報を集約するという思想である

内容と対象読者

本記事では 2 つのテーマを扱います。

1 つ目に、本の執筆環境ではどのようなツールを導入し、
どのような役割があるのかをご紹介します。

2 つ目に、執筆フローで導入した GitHub Oriented Writing という考え方をご紹介します。

今回解説する内容を実際に技術書典 12 での執筆で導入した結果、
少ない時間でもある程度のクオリティを維持しながらタスク管理ができたと感じています。
ゆえに、この機会に備忘録として残しておくとともに、この知識を皆さんにシェアしたいと考えました。

想定する読者は次のように考えています。

  • 技術書典や技術書執筆に興味がある方
  • なんらかのソフトウェア開発経験がある方
  • LaTeX やマークダウンなど文書を作成するためのデータ形式を知っている方

技術書オンリー同人誌即売会、技術書典という文化

まずは技術書典について紹介をしましょう。
技術書典とは日本最大の技術同人誌オンリー即売会です。

https://techbookfest.org/

たくさんの人が本を頒布し、たくさんの人がそれを買う、
技術のお祭りのようなイベントです。

記事執筆時点では 12 回開催されています。
第 7 回までは池袋サンシャインシティなどのオフライン会場で開催されていましたが、
パンデミックが起きてからはすぐにオンラインマーケットという形に切り替わりました。
おそらくここまで柔軟な対応ができる即売会運営は日本にいないのではないでしょうか......。

他にも技術書典は、次に挙げる点で他の同人誌即売会と比べて変わっていると私は感じています。

  • 頒布する本の金額が比較的高い
  • 一般参加者の購買意欲が高い
  • 運営サイドの徹底的なサポート
  • 物理本の頒布コストが低い

コミケやコミティアとは参加者層が違うのでちょっと文化も違ってきます。
頒布される、いわゆる薄い本ですが、だいたい 1000 円くらいが相場なのではないでしょうか。
同人誌にしては高いと感じますが、そもそも技術商業誌・専門書は相場が 3000 円~くらいなので技術者からしてみればたたき売りしてるみたいな金額に見えますよね。
しかも内容は商業誌よりもニッチで実践的なことがしばしばです。

参加者は趣味で開発・モノづくりをしている人だけではなく
会社でソフトウェアエンジニアをしている人も多いです。
本も、お仕事に直結する内容であったりするので
必然的に参加者の購買意欲は上がります。

すごいのは参加者だけではありません。技術書典はとにかく運営のサポートが手厚いです。
初めて本を作る場合、まず何から始めてよいのかわからないわけですが、
そういうときは技術書典公式 YouTube チャンネルの過去配信のアーカイブが役に立ちます。

YouTubeのvideoIDが不正ですhttps://www.youtube.com/c/techbookfest

はじめて参加するサークル向けに、
本の作り方やスケジュールをレクチャーする説明会イベントを書典開催前に毎回開かれているので初参加でも安心です。
しかも途中で分からないことがあった場合は技術書典公式 Discord で質問できます。

書典運営のサポート体制のことでしたら「あとから印刷」を語らずにはいられません。
同人誌は電子本と物理本の二種類を頒布できますが、物理本は電子版よりも制作コストが高めです。
本に関する知識も必要ですし、印刷所との連携無くして成り立たないのです。
加えて在庫管理は結構シビアな問題になりがちです。

あとから印刷という制度を使うと、物理本のデータを書典のフォームから入稿することでバックアップ印刷所である日光企画さんに引き継がれ、サークルが何もしなくても購入者に本がいきわたるのです。
しかもマーケット終了後に入稿するので頒布した冊数だけを印刷できます。
つまり在庫が残らない仕組みになっているのです。

https://blog.techbookfest.org/2021/06/26/tbf11-print-order/

私は本を読んだり書いたりするのが好きですが、こういう制度・文化的な側面が好きなのもあって書典に参加しています。
すごいぞ技術書典ということで長い前書きになりました。

本の執筆環境

それでは技術書典 12 で用いた環境を紹介していきます。
前提として、OS は Windows 10 Home を使用し、WSL は使っていません。

今回のプロジェクト構成は書典運営が公開してくれているTechBooster/ReVIEW-Templateというリポジトリをベースにしています。

https://github.com/TechBooster/ReVIEW-Template

最終的に出来上がった構成を図にしてみると次のようになりました。

img
最終的なシステム構成

VSCode と Re:VIEW 拡張による執筆

執筆には VSCode を用いました。
書典公式のリポジトリでは Atom が推奨されていますが VSCode でも拡張機能を入れることでちゃんと動作します。

執筆では Re:VIEW という言語を使用していまして、Re:VIEW の説明を公式サイトから引用すると次のようになります。

Re:VIEW は電子書籍と紙書籍のための、簡潔かつ強力なデジタル出版ツールです。コンピュータ書等の技術書籍(紙・電子)の商業出版や同人出版に利用されています。

https://reviewml.org/ja/

説明にもある通り、Re:VIEW の文法に倣って文章を書きビルドすることで
紙・電子どちらの文書に対しても組版してくれるものです。

Re:VIEW の文法の例を示します。
\LaTeXよりも簡単な文法だけど Markdown よりも表現力が高い、といったような印象を自分は受けました。拡張子は.re です。

article.re
= 章タイトル

//lead{
リード文
//}

== 節タイトル

=== 項タイトル

 * 箇条書き
 * 箇条書きhoge

//list[コードのラベル][プログラムコード キャプション]{
#include <stdio.h>
int main(){
  return 0;
}
//}

//image[画像の参照ラベル][画像のファイルパス]{
//}

わははは@<tt>{インラインコード}

VSCode で使うためには、拡張機能のメニューで「re:view」と検索して出てくる次の拡張機能をインストールしましょう。

https://marketplace.visualstudio.com/items?itemName=atsushieno.language-review

この拡張機能を入れることでシンタックスハイライトが有効になるほか、.re ファイルのリアルタイムプレビューも使えるようになります。

textlint と prh で校正・推敲

校正と推敲をするにあたり、textlint と prh というツールを導入しました。
どちらのツールも Node.js 環境を用いて動作するので VSCode が動作しているローカル環境にはインストールが必要です。

ソフトウェア開発をされている方には Linter はなじみのあるツールではありますが、
文書における Linter がまさに今回紹介する textlint です。

https://textlint.github.io/

textlint を導入すると、例えば「~だと思う」「かもしれない」のようなあいまいな表現を検知したり、半角英数字と全角の日本語の間を半角スペース空けるように設定したり、同じ接続詞の連続使用を検知したりできます。
実はこの記事の執筆にも導入しています。

続いて prh ですが、こちらは表記ゆれを検知して自動で直してくれるツールです。
例えば「なほるど->なるほど」や「web->Web」などシンプルな Typo や怪しい表記ゆれに対して有効です。

https://github.com/prh/prh

texlint と prh も Re:VIEW 同様 VSCode 拡張機能があるので、そちらをインストールして使いましょう。
また、ファイルを保存した瞬間に自動的に修正するような設定をしておくと執筆が捗ります。

settings.json
{
  // ...
  "editor.formatOnSave": true
  // ...
}

実際に VSCode で動かすと次のような画面になります。

img

Docker と Re:VIEW で本をビルドする

LaTeX 同様、Re:VIEW で書いた内容を本にするためにはビルドする必要があります。
ローカルでビルドする場合、当然ローカル環境に Re:VIEW がインストールされている必要があるのですが、そのままの Windows 環境で Re:VIEW を使うのはあまり推奨されていないみたいです。
ネットで情報を漁ってみると、WSL か Docker を使う方法がヒットします。

今回は Docker を使って本をビルドしました。
書典運営の一人である vvakame さんという方が Re:VIEW 用の Docker イメージを公開してくださっているのでそちらを利用します。

https://github.com/vvakame/docker-review

書典 12 では、次のようなバッチファイルを作成して
本をビルドしたい時に./build.batとコマンドを実行して使っていました。

build.bat
@echo off
@rem change mount directory name
docker run -it --rm -v /path/to/dir/:/book vvakame/review:5.0 /bin/bash -ci "cd /book/articles && review-pdfmaker config.yml"

こうすることでビルドが走り/articlesディレクトリに PDF ファイルが作成されます。

PR マージ時に本のビルドを Discord に送信

今回のプロジェクトは GitHub Actions による CI/CD 環境を作っています。
作ったとはいえ、すでに Techbooster さんのリポジトリには GitHub Actions で本をビルドして Artifacts として保存するように YAML ファイルに設定されています。
自分はこれに少し改変加えて、次に示す機能を実装しています。

  • PR 中の push をトリガーして textlint を実行
    • 提案内容をコメント
  • PR マージで本をビルド
  • ビルド終了後 Discord に本を送信

後述する GitHub Oriented Writing を実践する中で章ごとにブランチを切って Pull Request を出しているのですが、章が完成していなくても PR 作って push していました。
その際に WIP Bot を導入することで PR 名に[WIP]とプレフィックスを付けることで誤ってマージするのを防ぎました。

https://github.com/wip/app

textlint の実行結果をコメント

textlint は reviewdog というものを使って動作させていました。
この Actions を使うことでコードレビューを PR にコメントできます。

https://github.com/reviewdog/reviewdog

実は直接 reviewdog を扱ったわけではなく reviewdog と textlint を連携してくれるaction-textlintがあるのでそちらを使っています。

https://github.com/tsuyoshicho/action-textlint

実際に PR への Push をトリガーにした GitHub Actions は次のようになりました。

reviewdog.yml
name: reviewdog
on: [pull_request]
jobs:
  textlint:
    name: runner / textlint
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2
        with:
          submodules: true

      - name: Set Up Ruby
        uses: actions/setup-ruby@v1
        with:
          ruby-version: 2.6
          bundler-cache: true

      - name: Install Bundler
        run: gem install bundler

      - name: Use Node.js
        uses: actions/setup-node@v1
        with:
          node-version: "12.x"

      - name: Cache Yarn
        uses: actions/cache@v2
        with:
          path: ~/.cache/yarn
          key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
          restore-keys: |
            ${{ runner.os }}-yarn-

      - name: Yarn
        if: steps.cache.outputs.cache-hit != 'true'
        run: yarn --frozen-lockfile

      - name: textlint-github-pr-review
        uses: tsuyoshicho/action-textlint@v3
        with:
          github_token: ${{ secrets.github_token }}
          reporter: github-pr-review
          level: warning
          textlint_flags: "articles/*.re"

本のビルドと Discord への送信

本のビルドは元のリポジトリにある YAML ファイルを参考にしました。
vvakame さんが公開してくださっている Actions を使ってビルドすると、
ローカルの時と同様に/articles以下に PDF ファイルが生成されます。

https://github.com/TechBooster/ReVIEW-build-artifact-action

本がビルド出来れば、あとは煮るなり焼くなり毛利元就です。
ネットでいい感じに Discord へファイルを送信できる Actions を探したところ次の Actions がヒットしたのでこちらを使いました。
(確認したらリポジトリがアーカイブされていましたね)

https://github.com/ToppleTheNun/discord-scm-action

最終的に出来上がった設定はこちらです。

on_push.yml
name: Build Re:VIEW to make distribution file
# The workflow is triggered on pushes to the repository.
on:
  push:
    branches:
      - main

jobs:
  build:
    name: "on push"
    runs-on: ubuntu-20.04
    steps:
      # uses v2 Stable version
      # https://github.com/actions/checkout
      - name: checkout source
        uses: actions/checkout@v2

      # Build Artifacts
      - name: Build distribution file
        uses: TechBooster/ReVIEW-build-artifact-action@master

      # Upload Distribution file
      - name: Upload distribution file to github artifacts
        uses: actions/upload-artifact@v2
        with:
          name: Output documents
          path: ./articles/*.pdf

      # 通知
      - name: Discord Message Notify
        uses: appleboy/discord-action@0.0.3
        with:
          webhook_id: ${{ secrets.DISCORD_WEBHOOK_ID }}
          webhook_token: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
          color: "#48f442"
          args: ビルドDone.

      # discordへ送信
      - name: Send artifact to Discord
        uses: ToppleTheNun/discord-scm-action@v1.0.2
        with:
          discordWebhookId: ${{ secrets.DISCORD_WEBHOOK_ID }}
          discordWebhookToken: ${{ secrets.DISCORD_WEBHOOK_TOKEN }}
          artifacts: ./articles/webar-babylon-book.pdf

こんな感じで Discord に通知されていました。

img

GitHub Oriented Writing

執筆環境の話から変わり、今度は執筆ワークフローの話をしましょう。

今からご紹介する GitHub Oriented Writing は
技術書典が開催している説明会イベントで解説されていたものを参考にしています。
簡単に言うと、「執筆に関する情報はすべて GitHub にまとまっていたら幸せになれそうだ」
という思想のことを指します。

GitHub にはタスク管理、チームでのコラボレーション、外部への公開、などの用途に合わせて色々な機能があります。
ソフトウェア開発の現場ではよく使われている機能群ですが本の執筆にも十分使えるのです。

アイデア・作業ログを Discussion にメモ

みなさんは Discussion という機能を使っていますか。
最近リリースされた機能だからかリポジトリの設定で有効にしないと使えないようですね。
本来はフランクに質問をしたり、開発者がアイデアについて意見を集めたりする機能ですが個人で使うにも結構使えたりします。

今回はアイデアと作業ログをメモするのに使いました。
執筆を始める前に対象読者や章立てを考えたり、本の名前を考えたり、考えたことは基本メモしました。
また、執筆中に「あとでこの資料必要そうだな」とか「要検討事項だな」と思ったものをメモしたりしました。

img

初めて取り入れたので活用しきれていない感じがありますが、使ってよかったなと今は感じています。
スレッドをアイコン付きのカテゴリに分けられるのがお気に入りです。

Issue・Pull Request・Milestone・Project でタスク管理

執筆にとりかかる前、Discussion で決めた章立てに沿って issue を作成し、電子データの入稿日に Milestone を立てました。

img
書典 12 終了時点の Milestone

そしてソフトウェア開発と同じように Issue に紐づいた PR を作成し、それらを Project に紐づけます。

img

Project は β 版を使いました。
従来の Automated Kanban スタイルで Issue や PR が close されるとステータスが Done になるような自動化をしています。
β 版の Project は issue と PR を一覧で見られるので結構好きです。

今回実は執筆期間は実質 1 週間くらいしか取れなかったのですが、
この方法を導入することでかなりスムーズに進んだと感じますし、
タスクがどんどん消えていくのがモチベーションにつながったと感じています。

おわりに

同人誌の執筆方法は何通りもあり、絶対な正解は存在しないでしょう。
快適な環境を追い求めるとキリがないものです。
自分の方法もまだ改善できる点はいくつもあるし、これが合同誌になった場合、また違った形になることでしょう。
今回はその一例を紹介しましたが、この内容が少しでも皆さんの執筆ライフに貢献出来たら幸いです。

最後に宣伝

書典 12 で頒布した私の本ですが、イベント終了後もご購入いただけます。
是非チェックしてみてくださいませ。

https://techbookfest.org/product/6028242932727808?productVariantID=5465292979306496

参考文献

https://github.com/TechBooster/ReVIEW-Template

https://budougumi0617.github.io/2019/06/22/textlint-with-reviewdog-for-review/#tldr

https://efcl.info/2015/09/10/introduce-textlint/

https://techbookfest.org/product/6042605263519744

GitHubで編集を提案

Discussion