以下の内容はhttps://blog.amedama.jp/entry/textlint-create-simple-ruleより取得しました。


textlint でシンプルなルールを自作する

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-scriptstextlint-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.jsonmain と対応するように 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 のパッケージとして公開することになるだろう。





以上の内容はhttps://blog.amedama.jp/entry/textlint-create-simple-ruleより取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14