pre-commit で textlint を実行する

## はじめに

不意に GitHub Actions の Super Linter から以下のようなエラーが返ってきた

```
error  Incorrect usage of the term: “html”, use “HTML” instead  terminology
```

何者だろうと GitHub Actions のログを見ると `Linting [NATURAL_LANGUAGE] files...` の文字が

また新しい Linter が追加されたのか、、、

v4.8.2 で追加された　textlint によるものらしい

https://github.com/github/super-linter/releases/tag/v4.8.2

というわけで、 GitHub Actions で弾かれるものはローカルでも弾いておきたいので、 textlint を pre-commit で実行できるようにしました

textlint

https://github.com/textlint/textlint

pre-commit

https://github.com/pre-commit/pre-commit

自作の pre-commit 用 textlint mirror

https://github.com/RyoWakabayashi/pre-commit-mirrors-textlint

## textlint とは

textlint 自体はかなり古いもので、　GitHub のリリースを遡ると 1.3.0 が 2015年にリリースされています

ざっくり言うと文章校正ツールです

文章がルールに従っているかチェックし、可能ならば自動修正します

ESLint や Pylint が開発言語をチェックするのに対し、 
textlint はプレーンテキストや Markdown などの自然言語を対象としています

どういうチェックをするかはルール次第で、様々なルール集が使用できます

例えば、 Super Linter では terminology と言うルールが使われていました

Super Linter の textlint設定 `super-linter/TEMPLATES/.textlintrc`

```json
{
  "filters": {
    "comments": true
  },
  "rules": {
    "terminology": true
  }
}
```

`filters` で指定している `comments` は、コメントで特定範囲をチェックの対象外にするためのものです

textlint-rule-terminology は以下のリポジトリーで公開されています

https://github.com/sapegin/textlint-rule-terminology

これは英語表記の技術用語をチェックするためのルールです

公式から例を引用すると、以下のような大文字小文字やハイフンの有無などを、標準的な表記に統一してくれます

> Javascript → JavaScript
> NPM → npm
> front-end → frontend
> website → site
> Internet → internet

私の GitHub Actions では `html` が小文字だったために、標準的な `HTML` の大文字にしなさい、と指摘されたわけです

以前から、よく「これは大文字で書くのが正しかったっけ？」「２単語に分けて書くのが正しかったっけ？」と公式サイトで確認していますが、どうしても漏れが出るものです

README や技術的な文書などを書くときに非常に有用なツールと言えるでしょう

## コマンドラインでの使い方

- 必要な環境: Node.js

- インストール方法

※以降、グローバルの場合のコマンドになっています

```sh
npm install --global textlint
```

- ルールの追加

必要なルールを個別に npm でインストールします

`terminology` の場合

```sh
npm install --global textlint-rule-terminology
```

comments フィルターの場合

```sh
npm install --global textlint-filter-rule-comments
```

- 設定ファイルの作成

textlint を実行したいディレクトリーに `.textlintrc` を JSON 形式で記述

適用したいルールを `true` 、適用したくないルールを `false` にします

```json
{
  "rules": {
    "no-todo": false,
    "very-nice-rule": true
  }
}
```

- 無視ファイルの作成

特定のファイルやディレクトリー配下をチェック対象外にしたい場合、
`.textlintignore` を作成し、ファイル名を記載します

ワイルドカードが使用可能です

```text
aaa/bbb/xxx.md
node_modules/*
```

- 実行

現在のディレクトリー配下全てに対して実行する場合

```sh
$ textlint .

/Users/xxx/yyy/zzz.md
  50:19  ✓ error  Incorrect usage of the term: “html”, use “HTML” instead  terminology

✖ 1 problem (1 error, 0 warnings)
✓ 1 fixable problem.
Try to run: $ textlint --fix [file]
```

エラーがあったファイル、行番号、列番号、エラー内容が結果として表示されます

特定のファイルに対して実行する場合

```sh
textlint aaa/bbb/ccc.md
```

自動修正を行う場合

```sh
textlint --fix aaa/bbb/ccc.md
```

## VSCode での使い方

VSCode の Extension もあるので、入れておけば不適切な箇所を指摘してくれます

https://marketplace.visualstudio.com/items?itemName=taichi.vscode-textlint

![スクリーンショット 2021-11-19 9.17.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/34ceecf5-5fd7-0f14-ccf8-021885fb8a93.png)

:bulb: をクリックすれば修正オプションが表示され、自動修正も可能です

![スクリーンショット 2021-11-19 9.17.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/5aa3ef12-287f-e061-448c-bfdc45b463c1.png)

## pre-commit での使い方

私は常々 pre-commit で各種 Linter を動かしているので、 textlint もこれに組み込んでしまいたいと考えました

が、どうも pre-commit から呼ぶための hook がどこにもなさそうです

https://pre-commit.com/hooks.html

というわけで自作しました

と言っても大したことではなく、 `pre-commit-mirror-maker` で簡単に作れます

https://github.com/pre-commit/pre-commit-mirror-maker

インストール

``` sh
pip install pre-commit-mirror-maker
```

GitHub で `pre-commit-mirrors-textlint` リポジトリーを Public で作成

ローカルにクローン

```sh
git clone https://github.com/RyoWakabayashi/pre-commit-mirrors-textlint
```

クローンしたリポジトリー内に mirror を作成

```sh
pre-commit-mirror pre-commit-mirrors-textlint --language node --package-name textlint --files-regex '\.(md|mdown|markdown)$'
```

結果をプッシュ（タグも全てプッシュ）

```sh
cd pre-commit-mirrors-textlint
git push origin --tags
```

あとは適当に README を追加しましょう

以上で出来上がりです

https://github.com/RyoWakabayashi/pre-commit-mirrors-textlint

ローカルの pre-commit で使う場合、 `.pre-commit-config.yaml` に以下のように追記すれば実行できます

```yaml
  - repo: https://github.com/RyoWakabayashi/pre-commit-mirrors-textlint
    rev: v12.0.2
    hooks:
      - id: textlint
        files: \.(markdown|md)$
        additional_dependencies:
          - "textlint-filter-rule-comments"
          - "textlint-rule-terminology"
```

`additional_dependencies` には使用するルールの npm パッケージを記載してください

## 注意点

例えば `index.html` のようなファイル名や URL に含まれる文字もチェック対象になります

そのため、確認せずに自動修正すると意図しない表記になってしまう危険性があります

Markdown にファイル名を記載する場合は `` で囲んでコードにしてしまえば無視されます

また、 URL は基本的に直接記載せず、以下のようにリンクを貼りましょう

NG な書き方

```md
リンク: <xxx.html>
```

OK な書き方

```md
[リンク](xxx.html)

[リンク][link]

[link]: xxx.html
```

どうしても URL を書きたい場合、コメントでその行を無視させます

```md
<！- textlint-disable- >
リンク: <xxx.html>
<！- textlint-enable- >
```

コマンドとしての `node` を地の文に書くと `Node.js` に修正されるので、こちらも `node` とコードにします

## おわりに

今まで使ってきませんでしたが、 textlint は非常に便利なツールで、表記揺れを防ぐためにも是非使っていきたいですね

Super Linter で採用された以上、対応しないわけにはいかないのですが

日本語の校正もできるようなので、これも試してみたいと思います

https://fwywd.com/tech/textlint-proofreading