textlintで特定のルールのエラーを無視する


[textlint](https://github.com/textlint/textlint "textlint")には[さまざまなルール](https://github.com/textlint/textlint/wiki/Collection-of-textlint-rule)がありますが、特定の行や場所においてはルールを無効化したい場合があります。

例えば、[asciidwango/js-primer: JavaScriptの入門書](https://github.com/asciidwango/js-primer "asciidwango/js-primer: JavaScriptの入門書")という書籍では、表記揺れを防止するために[textlint-rule-prh](https://github.com/textlint-rule/textlint-rule-prh "textlint-rule-prh")というルールを使っています。

この書籍では、**匿名関数**と**無名関数**の表記揺れを防止するために**匿名関数**へ[統一する辞書](https://github.com/asciidwango/js-primer/blob/master/prh.yml#L132)が入っています。
しかし、どちらもよく使われる単語なので、「この書籍では無名関数の事を匿名関数と呼ぶ」という言及が必要です。

> このように関数式では、名前を持たない関数を変数に代入できます。
> このような名前を持たない関数を**匿名関数**（または無名関数）と呼びます。
> <https://asciidwango.github.io/js-primer/basic/function-declaration/>より

この時、この部分だけは[textlint-rule-prh](https://github.com/textlint-rule/textlint-rule-prh "textlint-rule-prh")を無効化する必要があります。

[textlint](https://github.com/textlint/textlint "textlint")ではそのような無効化を扱うフィルタールールという種類のルールが用意されています。

## コメントで指定範囲を無視する

フィルタールールの一種としてコメントで指定範囲を無効化できる[textlint-filter-rule-comments](https://github.com/textlint/textlint-filter-rule-comments "textlint-filter-rule-comments")があります。
このフィルタールールを有効化した場合は次のようにコメント(MarkdownならHTMLコメント)で特定のルールを無効化できます。


	<!-- textlint-disable prh -->
	
	このように関数式では、名前を持たない関数を変数に代入できます。
	このような名前を持たない関数を**匿名関数**（または無名関数）と呼びます。
	
	<!-- textlint-enable prh -->


導入方法は通常のルールと殆ど同じでnpmでインストールします。

	npm install textlint-filter-rule-comments
	
そして`filters`のフィールドに[textlint-filter-rule-comments](https://github.com/textlint/textlint-filter-rule-comments "textlint-filter-rule-comments")を追加するだけです。

```js
{
    "filters": {
        "comments": true
    }
}
```

## 正規表現で指定範囲を無視する

類似するフィルタールールとして指定文字列やパターンを無視できる[textlint-filter-rule-allowlist](https://github.com/textlint/textlint-filter-rule-allowlist)があります。こちらは文章全体で無視したいパターンを正規表現文字列で書けます。

```js
{
    "filters": {
        "allowlist": {
            "allow": [
                "ignored-word", // <= 特定の単語を無視
                "/\\d{4}-\\d{2}-\\d{2}/", // <= 日付っぽい表現を無視
                "/===IGNORE===[\\s\\S]*?===\/IGNORE===/m" // <= `===IGNORE===`で囲んだ範囲を無視
            ]
        }
    }
}
```

たとえば、[js-primer](https://asciidwango.github.io/js-primer/)だとコードをブラウザ上で実行できる[コンソールモード](https://github.com/asciidwango/js-primer/blob/master/CONTRIBUTING.md#%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%83%A2%E3%83%BC%E3%83%89 "コードのコンソールモード")のマクロとして`{{book.console}}`という特殊な文字列が自動で展開されるようになっています。
しかし、Markdown的にはただの文字列であるためなんらかのルールに引っかかる可能性があります。
そのため、[`/{{[a-zA-Z.]*?}}/`](https://github.com/asciidwango/js-primer/blob/c7169b4b316d6a2ef21e011466e8d7d65d281232/.textlintrc#L6 "&#34;/{{[a-zA-Z.]*?}}/&#34;")というパターンを文書全体で無視しています。

```json 
{
  "filters": {
    "comments": true,
    "allowlist": {
      "allow": [
        "/{{[a-zA-Z.]*?}}/",
        "と考えるかもしれません"
      ]
    }
}
```


ルールのオプションに無視リストを指定できる場合はそちらを優先した方が無意味な無効化が減って良いと思います。

## 例) 数式を無視する

QiitaなどMarkdownに数式の拡張(`$$`)をサポートしている場合があります。
これはMarkdownの標準ではないため、textlintは`$$`で囲んだ範囲もただのテキストとして扱ってしまいます。

これも[textlint-filter-rule-allowlist](https://github.com/textlint/textlint-filter-rule-allowlist)で`$$`で囲んだ範囲できます。
(ルールがエラーとして扱っても、そのエラーは無視される)

```json
{
    "filters": {
        "allowlist": {
            "allow": [
                "/\\$\\$[\\s\\S]*?\\$\\$/m"
            ]
        }
    }
}
```

数式の例)

```
$$
\begin{pmatrix}
1 & 0 & 0 \\\ 
0 & 1 & 0 \\\
0 & 0 & 1
\end{pmatrix}
$$
```

$$
\begin{pmatrix}
1 & 0 & 0 \\\ 
0 & 1 & 0 \\\
0 & 0 & 1
\end{pmatrix}
$$


## フィルターの作り方

textlintではフィルタールールもユーザーが作れるようになっています。
詳しくは次のドキュメントを参照すると良いですが、`shouldIgnore`というメソッドを使う以外は基本的に通常のルールの作り方と同じです。


- [textlint/filter-rule.md at master · textlint/textlint](https://github.com/textlint/textlint/blob/master/docs/filter-rule.md "textlint/filter-rule.md at master · textlint/textlint")

[textlint](https://github.com/textlint/textlint "textlint")がASTベースでチェックするのは誤検知を防止する目的が大きいので、すべての文章に万能なルールはないという前提にしています。そのため、すべてのルールはプラグインであり、フィルタールールもプラグインとなっています。

- [textlintから学んだこと](http://azu.github.io/slide/reactsushi/textlint.html "textlintから学んだこと")

textlintのコアロジックだけを取り出した[@textlint/kernel](https://github.com/textlint/textlint/tree/master/packages/textlint-kernel "@textlint/kernel")というコアモジュールがあるので、その上に便利な(最初から何でも入ってる)層を作ることもできます。

## .textlintignoreファイルで無視する

`.textlintignore`ファイルを使うことで、特定のファイルをLintの対象外にできます。

- [Ignoring Text · textlint](https://textlint.github.io/docs/ignore.html)
- [textlint 11.9.0 .textlintignoreの無視ファイルをサポート | Web Scratch](https://efcl.info/2021/03/21/textlintignore/)

## まとめ

[textlint](https://github.com/textlint/textlint "textlint")では、フィルタールールを使うことで指定した範囲のエラーを無効化できる。

- [textlint-filter-rule-comments](https://github.com/textlint/textlint-filter-rule-comments "textlint-filter-rule-comments")
- [textlint-filter-rule-allowlist](https://github.com/textlint/textlint-filter-rule-allowlist)
- [textlint-rule-filter - npm search](https://www.npmjs.com/search?q=textlint-rule-filter "textlint-rule-filter - npm search")