文章を自動で校正する

こんにちは、designing plus nineアドベントカレンダー8日目、担当のnkjmsssです。

designig plus nineのメンバーがとても面白い自己紹介を書いている中恐縮なのですが、そんなに面白い人間ではないので文章校正を少しでも幸せにするシステムを作ってみたという話について書きます。

作ったものは[こちら](https://github.com/nkjmsss/sample-textlint)で公開しています。

## 文章校正とは

まず、文章校正とはなんでしょうか。僕が所属していた団体でやっていたことを大別すると以下の2つになります。

- 表記揺れを正す
- 表現をより良いものにする

また、校正ルールは100個以上あったため、ここでこの全てを述べることはできませんが、特によく指摘した記憶があるのは以下のようなものです。

- 「！」「？」の後には全角スペースを挿入する
- 「皆様」「みなさま」ではなく「皆さま」に統一する
- 記号の半角、全角の使い分け

## 人間様のやる仕事ですか？？

ここまで読んで、指摘が低レベルすぎると思った方は多いと思います。本来的には、ライターになる人全てにこれらのルールを徹底させておかなければならないからです。

しかし、団体の規模が大きくなると末端の人たちにまでこれを習得してもらうのは難しいです。メインでライティングをする人は決まっていますが、担当外の人が書くこともそれなりにあります。たった1回書くだけの人に対し、100個以上あるルールを共有できるでしょうか。特に、僕の所属していた団体は単年度組織のため、1年ごとに人が入れ替わっています。そんな理想論は適用できるのでしょうか。

現状では、末端の人たちにまでルールを厳密に習得させるのができておらず、出来上がった文章を僕たちルールを知っている一部の人で校正することでクオリティを担保しています。ですが、正直言うと、上記のような低レベルなものは指摘したくないです。「低レベルで当たり前なこと」を指摘していると、「表現をどう変えたらよりよくできるか」を考えるのが難しくなるからです。

そこで、機械にできることは機械にやってもらおう、そのためのシステムをしっかり組もう、という話になります。

## ツールの選択

文章を校正するとなると、まず思いつくのは「Microsoft Word」を使う方法です。このソフトはとても有能で、校正ルールを追加していけば表記を統一させることが可能です。

ですが、この「ルールを追加していけば」というのが罠です。プログラマの方なら理解しやすいと思いますが、プロジェクトごとにルールを切り替えられない上、ルールの共有が困難なこの方法は不便極まりないです（僕が無知なだけだったら教えてください）。

そこで、僕はGithub + Travis CIでtextlintを用いる方法での校正がいいのではないかと考えました。この方法の副次的な効果として、

- 書いた文章の保存場所を一元化できる
- 版の管理が容易で、差分も表示できる
- masterブランチに完成版のみ置いて、他のブランチで作業するという住み分けが可能

というのがあり、Githubはプログラミング以外の用途でもかなりの力を発揮できると思います。

### textlintとは

一般的にlinterというと、プログラミングの文脈の中で出てくることが多く、バグの原因となりうる部分をチェックしてくれるツールです。今回使うtextlintはその派生系で、自然言語に対してチェックをかけるという変わり種になります。ありがたいことに、作者が日本人なこともあって日本語ドキュメントや日本語文法に対するlintルールが比較的充実しています。

## 下準備

ここから割とエンジニア向けの内容に入っていきます。

### Node.js

まずは、ローカル環境でtextlintが実行できるように準備をします。自分のPC上にNode.jsの環境を構築してあることが前提となるので、そこの部分の参考になる記事をまとめておきます。僕はMacユーザーでWindowsに詳しくないので、Macについてのみまとめます。が、Windowsでも大体の流れは同じだと思って大丈夫です。

1. しっかり環境構築したい人向け（[参考記事](https://qiita.com/rinpa/items/81766cd6a7b23dea9f3c)）
   1. anyenvのインストール
   2. nodenvのインストール
   3. Node.jsのインストール
2. お手軽に始めたい人向け
   1. [公式サイト](https://nodejs.org/ja/)からダウンロードし、インストール

今回は、v10.12.0を使っていきます。

### textlint

まずは、作業用フォルダを作ってそこに移動しておきます。CUIで行っても、GUIで行ってもどちらでも構いません。

```shell
$ mkdir textlint-sample
$ cd textlint-sample
```

nodenvを使っている方は、Node.jsのバージョンを指定しておきましょう。

```shell
$ nodenv local 10.12.0
```

次に、フォルダの初期化を行います。

```shell
$ npm init
```

これを打つと色々質問されますが、今は特に何も考えずにenterを連打しておけばとりあえずOKです。これが終わると、package.jsonが作られているはずです。

そして、textlintをインストールします。

```shell
$ npm install -D textlint
```

package.jsonにnpm scriptを登録しておきましょう。

```json
"scripts": {
  "lint": "textlint -f pretty-error docs/"
}
```

## 設定を作る

textlintはpluginableを目指して作られているので、この段階ではルールが一つも設定されていません。なので、自分でルールを追加していく必要があります。そこの部分の手間を省けるようにするために先人が[textlint-rule-preset-japanese](https://github.com/textlint-ja/textlint-rule-preset-japanese)のようにルールセットを作ってくれていますので、適宜使っていくといいと思います。ただ、あまり精度がいいとは言い切れない部分があるので使うかどうかは一考するべきだと思います。

この記事でやりたいことは、ひたすら表記揺れを直すことなので、[textlint-rule-prh](https://github.com/textlint-rule/textlint-rule-prh)のみインストールします。

```shell
$ npm install -D textlint-rule-prh
```

次に、textlintの設定ファイル（.textlintrc）を作ります。ファイル名がドットから始まるものは隠しファイルになるので、気をつけてください。

```json
{
  "rules": {
    "rulePaths": [
      "./rules/prh.yml"
    ]
  }
}
```

そして、ルール設定を作ったymlファイルへのパスを書き、prh.ymlを作ります。例として、文章中のスペース関連を設定したものを提示しておきます。

```yaml
# prh version
version: 1
rules:
  # 感嘆符の後には全角スペース（半角ではなく）
  - expected: $1　$2
    patterns: /([！？]) ?((?!　).*)/
    specs:
      - from: 感嘆符！の後には全角スペース
        to: 感嘆符！　の後には全角スペース

  # 文章中のスペースを消す（ひらがな・カタカナ・漢字の間のもの）
  - expected: $1$2
    patterns: /([\u3041-\u3096]|[\u30A1-\u30FA]|[々〇〻\u3400-\u9FFF\uF900-\uFAFF]|[\uD840-\uD87F][\uDC00-\uDFFF])[ 　]([\u3041-\u3096]|[\u30A1-\u30FA]|[々〇〻\u3400-\u9FFF\uF900-\uFAFF]|[\uD840-\uD87F][\uDC00-\uDFFF])/
    specs:
      - from: 文章中の スペースはダメ
        to: 文章中のスペースはダメ
```

## 実際に走らせてみる

```
この文はOKです。
この文 はスペースが入っているためにNGです。
あ！全角スペースが入っていないためにこれもNGです。
これ！　はOKです
これ！ は半角スペースなのでダメです。
```

上記のサンプルテキストに対しtextlintをかけてみましょう。

```shell
$ npm run lint sample.txt
```

こうすると、以下のようにエラーを返してくれます。

![error.png](https://qiita-image-store.s3.amazonaws.com/0/296046/04fd91ed-81ef-46a5-d15e-a88a11fed6e1.png)


また、これらに関しては以下のようにすると自動修正できます。

```shell
$ npm run lint sample.txt —-fix
```

## Github × Travis CI

本当はもっとしっかりルールを作り込んでいくべきですが、この記事ではルールを作ることよりも文章校正のシステムを作ることに焦点を当てたいので、Github連携の話に移っていきます。

### 準備-1

.gitignoreを作っておかないと痛い目を見るので、今のうちに作っておきましょう。書く内容はたったこれだけです。

```
node_modules
```

では、Githubにリモートリポジトリを作成し、指示にしたがって今回の作業フォルダをGithubにアップロードします。

![github-1.png](https://qiita-image-store.s3.amazonaws.com/0/296046/10b16b71-af06-3f5c-ee40-b67bf984b871.png)


```shell
$ git init
$ git add .
$ git commit -m "first-commit"
$ git remote add origin ######（各自のURL）
$ git push -u origin master
```

### 準備-2

GithubにTravis CIのアプリケーションを追加します。

https://travis-ci.com/ にアクセスし、アカウントを作ります。注意点として、https://travis-ci.org/ という古いバージョンがありますが、こちらだと後述のGithub Checks APIに対応していないため間違えないようにしてください（移行もできますが、無駄な手間になります）。登録にはGithubのOAuth認証を用いると楽でしょう。

登録ができたら、Githubにアプリを追加します。以下の画面で、Activeteを押します。

![screencapture-travis-ci-account-repositories-2018-12-08-16_26_44.png](https://qiita-image-store.s3.amazonaws.com/0/296046/148cab4f-4d7a-e51a-7a0a-fbf45fe50396.png)


すると、以下のような画面が出てくるので、許可しましょう。特に何も考えずにAll repositoriesに許可してしまうのが楽だとは思います（僕はそうしませんでしたが）。

![screencapture-github-apps-travis-ci-installations-new-permissions-2018-12-08-16_27_02.png](https://qiita-image-store.s3.amazonaws.com/0/296046/abe960ed-a30c-70dc-fde8-b6e143d3daf0.png)


しかし、これだけでは準備不足で、まだTravis CI側で自動チェックが走りません。そこで、次のステップに進みます。

### 準備-3

Travis CIは、「.travis.yml」のあるレポジトリに対して処理を行うので、そのファイルを作り以下のように記述します。

```yaml
language: node_js
node_js: 10.12.0
cache: npm
sudo: false
script: npm run lint
```

そして、pushします。これで、pushの度に自動でtextlintが走ってくれるようになりました。

### 実行

docs/sample.txtを編集してPull Requestを送ってみましょう。

![screencapture-github-nkjmsss-sample-textlint-edit-master-docs-sample-txt-2018-12-08-16_33_35.png](https://qiita-image-store.s3.amazonaws.com/0/296046/a96be266-ee66-af01-6396-dffcbc288632.png)


そうすると、以下のようにチェックが走り、今回はダメなものを送ったのでFailしました。詳細はChecksのタブを見れば確認できます。

![screencapture-github-nkjmsss-sample-textlint-pull-1-2018-12-08-16_38_29.png](https://qiita-image-store.s3.amazonaws.com/0/296046/d7a01781-0d02-5b93-3dd9-8356a3c4bfba.png)


###おまけ

Github側でbranchを保護するルールを作っておきます。こうすることで、masterブランチに直接pushできなくなります。masterの更新をするにはPull Requestをしなければならなくなり、そしてPull RequestをするにはCIによるチェックを抜けなければならないとできます。

なお、最後のオプションの「Include administrators」のチェックは適宜考えてください。このリポジトリのadmin権限を持っている人が誤ってmasterを変更することを防ぎたいならチェックしておくといいと思います。

![screencapture-github-nkjmsss-sample-textlint-settings-branch_protection_rules-new-2018-12-08-16_51_18.png](https://qiita-image-store.s3.amazonaws.com/0/296046/a9aad2c8-ed85-8a51-8870-25e7f9e701d3.png)


## 終わりに

それなりに手間がかかりましたが、これで自動で文章校正することが可能になりました。このシステムをうまく使えば、細かな表記統一は機械にやらせられるので、表現の改善に全力を注げるようになると思います。

まだ改善点はあり、Checksタブの中でどこにエラーがあったのかが確認できないので、そこについての解決策がわかったら更新します。長文・駄文でしたが読んでいただきありがとうございました。