textlint 1 は自然言語向けの Linter のひとつ。 textlint はデフォルトではチェックするルールが何も組み込まれていない。 そのため必要に応じてルールや、複数のルールを束ねたプリセットを自分でインストールして使用する。
textlint のルールやプリセットは npm のパッケージとして実装される。 多くのユースケースでは、公開されている既存のルールやプリセットを組み合わせることで実現できる。
一方で、それでは実現が難しいケースも存在する。 そこで、今回は勉強のためにシンプルなルールを自作してみた。 ルールは何かしら単一のチェックする内容を表現するときに実装する。
使った環境は次のとおり。
$ sw_vers ProductName: macOS ProductVersion: 26.3.1 BuildVersion: 25D2128 $ uname -srm Darwin 25.3.0 arm64 $ npm --version 11.11.0 $ node --version v25.8.1
もくじ
下準備
下準備として Node.js をインストールしておく。
$ brew install node
パッケージを作成する
ここからは textlint のルールを作成していく。
textlint のルールとなるパッケージは命名規則が決まっている。
具体的には、パッケージ名にプレフィックスとして textlint-rule- を使用する。
プレフィックス以降に、そのルールを表した名前を入れる。
今回は文章に「ぬるぽ」が含まれているとエラーになるルールを作ってみよう。
命名規則からパッケージ名は textlint-rule-no-null-pointer-exception にする。
パッケージの作業場所となるディレクトリを用意する。
$ mkdir -p textlint-rule-no-null-pointer-exception $ cd textlint-rule-no-null-pointer-exception
npm のパッケージを作るときはメタデータを記述した package.json が必要になる。
そこで、ほとんど最低限の内容を記述した package.json を次のように用意した。
npm init コマンドなどでインタラクティブに作っても良い。
{ "name": "textlint-rule-no-null-pointer-exception", "version": "0.0.1", "description": "ga!", "type": "module", "main": "index.js", "scripts": { "test": "textlint-scripts test" } }
scripts 以下にある記述は、後ほどテストで使用する内容になっている。
ルールの開発に必要なパッケージをインストールする。
textlint-scripts と textlint-tester は主にテストで使用する。
$ npm install --save-dev textlint textlint-scripts textlint-tester
これで node_modules ディレクトリに上記のパッケージがインストールされる。
$ ls node_modules | grep textlint @textlint textlint textlint-scripts textlint-tester
また package.json に依存パッケージとして追加される。
$ cat package.json { "name": "textlint-rule-no-null-pointer-exception", "version": "0.0.1", "description": "ga!", "type": "module", "main": "index.js", "scripts": { "test": "textlint-scripts test" }, "devDependencies": { "textlint": "^15.5.2", "textlint-scripts": "^15.5.2", "textlint-tester": "^15.5.2" } }
ルールを関数として実装する
package.json の main と対応するように index.js を作る。
このファイルに、次のようにルールの具体的な処理を記述する。
// ルールに対応する処理を記述した関数を export する export default function (context, options = {}) { // 処理に必要なオブジェクトは関数の引数として得られる const { Syntax, getSource, RuleError, report, locator } = context; return { // AST のオブジェクト毎にチェックする処理が書ける // 文字列の中身を見るだけなら Syntax.Str で良い [Syntax.Str](node) { // ノードに含まれるテキストを得る const text = getSource(node); // 特定の文字列が含まれるかチェックする (見つかったら違反) const matches = text.matchAll(/ぬるぽ|ヌルポ/g); // 特定の文字列が見つかった場合のループ for (const match of matches) { // テキストの中で見つかった場所を求める const index = match.index ?? 0; const length = match[0].length; const matchRange = [index, index + length]; // ルールに違反したことを RuleError で伝える const ruleError = new RuleError("ガッ!", { padding: locator.range(matchRange), }); // report() 関数を使って違反の詳細を報告する report(node, ruleError); } }, }; }
ルールにテストを記述する
次に、ルールにテストを書いて動作を確かめる。
テスト用のディレクトリを用意する。
$ mkdir -p test
textlint のルールは textlint-tester というパッケージを使うとテストが書きやすい。
次のように test/index.test.js として用意する。
import TextLintTester from "textlint-tester"; // テストする対象を import する import rule from "textlint-rule-no-null-pointer-exception"; // TextLintTester を使ってテストが書ける const tester = new TextLintTester(); tester.run("no-null-pointer-exception", rule, { // 違反していないパターン valid: [ "こんにちは", "NullPointerException", ], // 違反しているパターン invalid: [ { // 違反しているテキスト text: "ぬるぽ", // 違反したときのメッセージと場所 errors: [ { message: "ガッ!", range: [0, 3] } ] }, { text: "ヌルポ", errors: [ { message: "ガッ!", range: [0, 3], } ] } ] });
テストがルールを import できるように、パッケージをリンクする。
$ npm link textlint-rule-no-null-pointer-exception
これでパッケージが開発用にインストールされた状態になる。
$ ls node_modules | grep textlint @textlint textlint textlint-rule-no-null-pointer-exception textlint-scripts textlint-tester
npm run test コマンドを実行してテストする。
$ npm run test > textlint-rule-no-null-pointer-exception@0.0.1 test > textlint-scripts test no-null-pointer-exception ✔ ぬるぽ ✔ ヌルポ ✔ こんにちは ✔ NullPointerException 4 passing (8ms)
ちゃんとテストがパスした。 ルールが正常に動作しているようだ。
コマンドラインから動かしてみる
テストで動作が確認できたので、次はコマンドラインから動かしてみよう。
サンプルとなるテキストを適当に用意する。
$ cat << EOF > /tmp/nullpo.md # 「NullPointerExceptionを「ぬるぽ」と呼ぶスレ ∧_∧ ( ´∀`)< ぬるぽ EOF
インストールされた textlint コマンドに --rule オプションで自作したルール名を指定する。
このときルール名には textlint-rule のプレフィックスはつけない。
$ ./node_modules/.bin/textlint --rule no-null-pointer-exception -f pretty-error /tmp/nullpo.md no-null-pointer-exception: ガッ! /tmp/nullpo.md:1:26 v 0. 1. # 「NullPointerExceptionを「ぬるぽ」と呼ぶスレ 2. ^ no-null-pointer-exception: ガッ! /tmp/nullpo.md:4:9 v 3. ∧_∧ 4. ( ´∀`)< ぬるぽ 5. ^ ✖ 2 problems (2 errors)
ちゃんとルールに違反した箇所がエラーになっている。
まとめ
今回は勉強のために textlint のシンプルなルールを自作してみた。 実際に自作したルールを使う際には、必要に応じて Git のリポジトリや npm のパッケージとして公開することになるだろう。