textlintのセットアップ&使い方

## 「textlint」とは？

Node.js製の自然言語リンターです。
ルールは1つもバンドルされておらず、様々なルールを自分でインストールして使うのが特徴です。

## 環境

- OS：macOS Monterey 12.4
- Node.js：v16.15.1
- textlint：v12.2.1

## セットアップ

textlintやルールをセットアップします。

### textlint

まずはtextlint本体をセットアップします。

https://github.com/textlint/textlint

#### インストール

textlintはNode.js製なのでnpmでインストールします。

```shell-session
$ npm install textlint --save-dev
```

私はローカルにインストールし、 `npx` を付けて実行しています。
グローバルにインストールする場合は `--location=global` を付けてください。

開発時のみ使うので `--save-dev` を付けています。

#### 設定ファイルの作成

プロジェクトのルートに `.textlintrc` を作成します。

```diff_json:.textlintrc
+ {
+  "rules": {
+  }
+ }
```

#### スクリプトの追加

`npm run lint` でリントの実行、 `npm run fix` で自動修正できるように、スクリプトを追加します。

```diff_json:package.json
{
  "devDependencies": {
    "textlint": "^12.2.1"
+  },
+  "scripts": {
+    "lint": "npx textlint ./Content/posts/*.md"
+    "fix": "npx textlint --fix ./Content/posts/*.md"
  }
}
```

私はPublish [^publish] で作成した全記事に対し、textlintを実行するように設定しています。
引数に渡すファイルパスは、プロジェクトに応じて変更してください。

[^publish]: Swift製の静的サイトジェネレータ。https://qiita.com/uhooi/items/57e040df2f4aa7f62d89

#### Node.js関連ファイルをバージョン管理から無視する

Node.jsの関連ファイルをバージョン管理の対象外にします。
Gitを使っている場合、以下を `.gitignore` に追加するのみでOKです。

```diff:.gitignore
+ # Node.js
+ node_modules
```

これでtextlint本体のセットアップは完了です。

### textlint-filter-rule-comments

本体のセットアップ後は、プラグインやルールをインストールします。

コメントで括った範囲のルールを無効にするプラグインです。

https://github.com/textlint/textlint-filter-rule-comments

#### インストール

npmでインストールします。

```shell-session
$ npm install textlint-filter-rule-comments --save-dev
```

#### 設定ファイルの編集

`.textlintrc` を編集し、プラグインを有効にします。

```diff_json:.textlintrc
{
  "rules": {
    ...
+ },
+ "filters": {
+   "comments": true
  }
}
```

#### 使い方

ルールを無効化したい範囲を、特定のコメントで括るのみです。

```diff_markdown:foo.md
+ 
+ <!-- textlint-disable ja-technical-writing/no-doubled-conjunction -->
+ 
適当な文字列です。適当な文字列です。適当な文字列です。適当な文字列です。適当な文字列です。適当な文字列です。適当な文字列です。適当な文字列です。適当な文字列です。適当な文字列です。
+ 
+ <!-- textlint-enable ja-technical-writing/no-doubled-conjunction -->
+ 
```

コメントの前後に空白行が必要なことに注意です。

無効化したいルールが複数ある場合、カンマ区切りで書きます。

```markdown
<!-- textlint-disable ルール1,ルール2,... -->
```

### textlint-rule-preset-ja-technical-writing

技術文書向けのルールプリセットです。

https://github.com/textlint-ja/textlint-rule-preset-ja-technical-writing

#### インストール

npmでインストールします。

```shell-session
$ npm install textlint-rule-preset-ja-technical-writing --save-dev
```

#### 設定ファイルの編集

`.textlintrc` を編集します。
内容は必要に応じて変更してください。

```diff_json:.textlintrc
{
  "rules": {
+   "preset-ja-technical-writing": {
+     "no-exclamation-question-mark": false,
+     "max-kanji-continuous-len": {
+       allow: [
+         "世界開発者会議"
+       ]
+     }
+   }
  }
}
```

私は感嘆符（ `！` ）や疑問符（ `？` ）を使いたいため、 `no-exclamation-question-mark` を `false` にしています。

漢字のみが続く最大の長さはデフォルトで6文字です。
特定の単語のみ7文字以上を許可したい場合、 `max-kanji-continuous-len` の `allow` にホワイトリスト形式で追加します。

### textlint-rule-period-in-list-item

箇条書きの末尾に、ピリオド（ `.` ）や句点（ `。` ）を許可しないルールです。

https://github.com/textlint-rule/textlint-rule-period-in-list-item

#### インストール

npmでインストールします。

```shell-session
$ npm install textlint-rule-period-in-list-item --save-dev
```

#### 設定ファイルの編集

`.textlintrc` を編集します。
内容は必要に応じて変更してください。

```diff_json:.textlintrc
{
  "rules": {
+   "period-in-list-item": true
  }
}
```

### textlint-rule-preset-ja-spacing

日本語のスペース関連のルールプリセットです。

https://github.com/textlint-ja/textlint-rule-preset-ja-spacing

#### インストール

npmでインストールします。

```shell-session
$ npm install textlint-rule-preset-ja-spacing --save-dev
```

#### 設定ファイルの編集

`.textlintrc` を編集します。
内容は必要に応じて変更してください。

```diff_json:.textlintrc
{
  "rules": {
+   "preset-ja-spacing": {
+     "ja-space-between-half-and-full-width": {
+       "space": "always"
+     },
+     "ja-space-around-code": {
+       "before": true,
+       "after": true
+     }
+   }
  }
}
```

私は以下のルールを適用するため、設定を追加しています。

- アルファベットと日本語の間に半角スペースを入れる
- インラインコード（ `こういうやつ` ）の前後に半角スペースを入れる

### textlint-rule-no-mixed-zenkaku-and-hankaku-alphabet

全角と半角アルファベットの混在をチェックするルールです。

https://github.com/textlint-ja/textlint-rule-no-mixed-zenkaku-and-hankaku-alphabet

#### インストール

npmでインストールします。

```shell-session
$ npm install textlint-rule-no-mixed-zenkaku-and-hankaku-alphabet --save-dev
```

#### 設定ファイルの編集

`.textlintrc` を編集します。
内容は必要に応じて変更してください。

```diff_json:.textlintrc
{
  "rules": {
+   "no-mixed-zenkaku-and-hankaku-alphabet": true
  }
}
```

デフォルトでは半角アルファベットのみ許可されており、全角アルファベットが含まれているとエラーになります。

## textlintの使い方

`npm run lint` を実行するのみです。

どのファイルのどこに、どのようなエラーがあるか出力されます。

```shell-session
$ npm run lint

> lint
> npx textlint ./Content/posts/*.md


/Users/uhooi/Documents/Repos/GitHub/ios-osushi/website/Content/posts/011-20220613.md
  41:14   ✓ error  Should remove period mark("。") at end of list item  period-in-list-item
  49:24   ✓ error  Should remove period mark("。") at end of list item  period-in-list-item
  55:142  ✓ error  Should remove period mark("。") at end of list item  period-in-list-item
  56:16   ✓ error  Should remove period mark("。") at end of list item  period-in-list-item
  68:16   ✓ error  Should remove period mark("。") at end of list item  period-in-list-item
  74:39   ✓ error  Should remove period mark("。") at end of list item  period-in-list-item

✖ 6 problems (6 errors, 0 warnings)
✓ 6 fixable problems.
Try to run: $ textlint --fix [file]

```

`npm run fix` を実行すると、 `fixable problems` のエラーが自動で修正されます。

```shell-session
$ npm run fix

> fix
> npx textlint --fix ./Content/posts/*.md


/Users/uhooi/Documents/Repos/GitHub/ios-osushi/website/Content/posts/011-20220613.md
  41:14   ✔   Should remove period mark("。") at end of list item  period-in-list-item
  49:24   ✔   Should remove period mark("。") at end of list item  period-in-list-item
  55:142  ✔   Should remove period mark("。") at end of list item  period-in-list-item
  56:16   ✔   Should remove period mark("。") at end of list item  period-in-list-item
  68:16   ✔   Should remove period mark("。") at end of list item  period-in-list-item
  74:39   ✔   Should remove period mark("。") at end of list item  period-in-list-item

✔ Fixed 6 problems

```

自動修正されないエラーは、手動で修正したり、ルールを無効にしたりなどしてください。

## CI環境の構築

GitHub ActionsでCI環境を構築します。

```yaml:ci.yml
name: CI

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

permissions:
  contents: read

jobs:
  textlint:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-node@v3
      with:
        node-version: 16
        cache: 'npm'
    - run: npm install
    - run: npm run lint
```

## おわりに

日本語の校正環境が整いました。
これできれいに日本語の記事を書けます :relaxed: 

## 参考リンク

- [技術文書を書くためのtextlint校正ルールセット | Web Scratch](https://efcl.info/2016/07/13/textlint-rule-preset-ja-technical-writing/)
- [textlintを導入する by uhooi · Pull Request #77 · ios-osushi/website](https://github.com/ios-osushi/website/pull/77)