Back to blog
Jan 13, 2023
4 min read

ブログにTextlintを導入してpre-commitとCIを構築する【文体を自動で整える】

ブログにTextlintを導入してpre-commitとCIを構築する【文体を自動で整える】

はじめに

こんにちは、こふです。

ブログなり、サイトなり、自分で資料を作るなり、文章を書く機会が比較的多いです。

疲れていたり、ぼーっとしていると、気づかぬうちに表現にブレが生じてしまう、誤字脱字があるため予防したいと思い、工夫をすることにしました。

(自分の過去の記事をたまに読み返すと、誤字脱字も表現のブレも多くてビビっていますが、全てて読むのは辛いので、このツールでなんとかします。文章の改善はツールに頼らず自分でやります。)

手順

大まかな手順をまとめます。

  1. Textlint を導入する
  2. プラグインを導入する
  3. textlint コマンドを作る
  4. pre-commit を設定する
  5. ルールを無視して良い箇所を指定する
  6. CI を設定する

Textlint を導入する

リポジトリはtextlint/textlint: The pluggable natural language linter for text and markdown.です。

textlint のインストール・初期化をします。当然、開発環境のみで使うパッケージなので-Dオプションをつけます。

npm install -D textlint
npx textlint --init

textlintがインストール済みであればnpxコマンドでインストールは発生しません。

プラグインを導入する

一気にたくさんのプラグインを入れても仕方がないし、対応に困るので 1 つだけ入れて様子見します。コミットも分けてるので最悪 revert します。

textlint-ja/textlint-rule-no-dropping-the-ra: ら抜き言葉をチェックする textlint ルールを入れます。

npm install -D textlint-rule-no-dropping-the-ra

.textlintrcを書き換えます。単にルールを有効にするだけ。

{
    "rules": {
        "no-dropping-the-ra": true
    }
}

動かしてみると次のようになります。プロジェクト配下のsrc/dataMarkdown を配置しているため、僕はこのように入力しています。

❯ npx textlint src/data

PATH_TO_BLOG/src/data/dummy.md
  1:3  error  ら抜き言葉を使用しています。  no-dropping-the-ra

当然ですが、直すと消えました。

textlint コマンドを作る

Markdown に対してのみ動かすので、package.jsonにコマンドを作ります。

JS / TSなどのプログラム中のコメントは英語で書く+日本語だとしても開発者しか見ないのでらぬき言葉だったとしても何ら問題はないです。そのため、Markdown に対してのみ実行したいです。

また、なぜコマンドを作るかと言うと、zsh で補完が効くから、CI でコマンドを使うから、です。

ESLint と同様に--fixオプションが使えますが、--fixして勝手に整形されると自分が困るため設定しません。

なぜなら、メンテナンスされてるか分からないプラグインがある可能性があるからです。

textlint/textlint: The pluggable natural language linter for text and markdown.にオプションなど記載あります。

{
    ...
    "scripts":{
        ...
        "textlint": "textlint --cache **/*.md",
        ...
    }
    ...
}

キャッシュファイルは当然生成されるのでgitignoreしましょう。

.textlintcache

これで npm スクリプトとして動かせます。

❯ npm run textlint

> textlint
> textlint --cache **/*.md


PATH_TO_BLOG/src/data/dummy.md
  1:3  error  ら抜き言葉を使用しています。  no-dropping-the-ra

pre-commit の設定をする

これらをインストールし、huskyだけ初期設定します。

npm install husky -D
npm pkg set scripts.prepare="husky install"
npm run prepare
npm install -D lint-staged
npx husky add .husky/pre-commit "npx lint-staged"

常に動かすと重い+実行を忘れるため、良いことがないので pre-commit に追加して動かしたいのです。

当然、全てに対してではなく、コミット前のステージングしたファイルだけです。そのためlint-stagedを使っています。また、以下のスクリプトは非常にシンプルにしていますが、本当は色々オプションを付けています。書き出したらキリもない・・・

{
  ...
  "lint-staged": {
    "*.md": [
      "textlint --cache"
    ],
    "*.{js,jsx,ts,tsx,json,css,md}": [
      "eslint --fix",
      "prettier --write"
    ]
  },
  ...
}

"*.{js,jsx,ts,tsx,json,css,md}": [としていますが、JS系しか ESLint で対応できないので以下のように設定しています(補足)。

**/*.md
**/*.css
**/*.json

当然、以下のように分けても良いです。

{
  ...
  "lint-staged": {
    "*.md": [
      "textlint --cache"
    ],
    "*.{js,jsx,ts,tsx}": [
      "eslint --fix",
    ],
    "*.{js,jsx,ts,tsx,json,css,md}": [
      "prettier --write"
    ]
  },
  ...
}

実際に動かすことで確かめます。あえてルールを無視するファイルであるdummy.mdを書きます。

食べれる

dummy.mdのら抜きをコミット出来なければ良いです

❯ git commit
✔ Preparing lint-staged...
❯ Running tasks for staged files...
  ❯ package.json — 1 file
    ❯ *.md — 1 file
      ✖ textlint --cache [FAILED]
    ❯ *.{js,jsx,ts,tsx,json,css,md} — 1 file
      ✖ eslint --fix [KILLED]
      ◼ prettier --write
↓ Skipped because of errors from tasks. [SKIPPED]
✔ Reverting to original state because of errors...
✔ Cleaning up temporary files...

✖ textlint --cache:

PATH_TO_BLOG/src/data/dummy.md
  1:3  error  ら抜き言葉を使用しています。  no-dropping-the-ra

✖ 1 problem (1 error, 0 warnings)


✖ eslint --fix failed without output (KILLED).
husky - pre-commit hook exited with code 1 (error)

「食べれる」→「食べられる」と修正します。

❯ git commit
✔ Preparing lint-staged...
❯ Running tasks for staged files...
  ❯ package.json — 1 file
    ✔ *.md — 1 file
    ❯ *.{js,jsx,ts,tsx,json,css,md} — 1 file
      ✔ eslint --fix
      ⠸ prettier --write
◼ Applying modifications from tasks...
◼ Cleaning up temporary files...

これでコミットで動くぞ。

ルールを無視して良い箇所を指定する

本ブログでら抜き言葉の例を書くと、それもら抜き言葉のエラーを吐いてしまいダメです。ブログが公開できません。

ESLint と同様に指定した箇所を無視するようにします。

パッケージをインストールします。

npm install -D textlint-filter-rule-comments

設定ファイルを追記します。

{
    ...
    "filters": {
        "comments": true
    },
    ...
}

本文にルールを適用します。

<!-- textlint-disable -->

```md
食べれる
```

<!-- textlint-enable -->

<!-- textlint-disable -->

「食べれる」→「食べられる」と修正します。

<!-- textlint-enable -->

これでコミットできました。

✦ ❯ git commit
✔ Preparing lint-staged...
❯ Running tasks for staged files...
  ❯ package.json — 1 file
    ✔ *.md — 1 file
    ❯ *.{js,jsx,ts,tsx,json,css,md} — 1 file
      ✔ eslint --fix
      ⠧ prettier --write
◼ Applying modifications from tasks...
◼ Cleaning up temporary files...

参照:Ignoring Text · textlint

CI を設定する

特に難しいことはなく、ESLint と同様に静的解析を動かして落ちたらビルドが動かないだけです。

詳細は分量多いので載せませんが、develop ブランチと、そのブランチへのプルリクエスト時のみ動かしてます。

JS / TS / JSX / TSX などの静的解析 → テスト → ビルド →Slack への通知を行っています。

---
- run: npm run textlint

補足

VSCode 拡張機能は使わないです。

常に視覚的に見えるのはうざい(口悪い)ので、僕は入れません。

ただ、lint-staged では過去のファイルに対してエラーを吐かないので、一応常に目に入るようにしたい人は VSCode 拡張機能を入れるのもありです。

プラグイン

たくさんあるので、随時追加しますが、自作したほうが良い気もしますね。

おわりに

これでより良い、表記の整った文章に少しずつ変えていけるし、これからの文章は確実に良い表記になる。

あとは文章の構成能力を上げるなり、伝え方に注力しよう。