
ブログにTextlintを導入してpre-commitとCIを構築する【文体を自動で整える】
2023-01-13
2023-01-13
はじめに
こんにちは、こふです。
ブログなり、サイトなり、自分で資料を作るなり、文章を書く機会が比較的多いです。
疲れていたり、ぼーっとしていると、気づかぬうちに表現にブレが生じてしまう、誤字脱字があるため予防したいと思い、工夫をすることにしました。
(自分の過去の記事をたまに読み返すと、誤字脱字も表現のブレも多くてビビっていますが、全てて読むのは辛いので、このツールでなんとかします。文章の改善はツールに頼らず自分でやります。)
手順
大まかな手順をまとめます。
- Textlint を導入する
- プラグインを導入する
- textlint コマンドを作る
- pre-commit を設定する
- ルールを無視して良い箇所を指定する
- CI を設定する
Textlint を導入する
リポジトリはtextlint/textlint: The pluggable natural language linter for text and markdown.です。
textlint のインストール・初期化をします。当然、開発環境のみで使うパッケージなので-D
オプションをつけます。
terminal1npm install -D textlint 2npx textlint --init
textlint
がインストール済みであればnpx
コマンドでインストールは発生しません。
プラグインを導入する
一気にたくさんのプラグインを入れても仕方がないし、対応に困るので 1 つだけ入れて様子見します。コミットも分けてるので最悪 revert します。
textlint-ja/textlint-rule-no-dropping-the-ra: ら抜き言葉をチェックする textlint ルールを入れます。
terminal1npm install -D textlint-rule-no-dropping-the-ra
.textlintrc
を書き換えます。単にルールを有効にするだけ。
.textlintrc1{ 2 "rules": { 3 "no-dropping-the-ra": true 4 } 5}
動かしてみると次のようになります。プロジェクト配下のsrc/data
に Markdown
を配置しているため、僕はこのように入力しています。
terminal1❯ npx textlint src/data 2 3PATH_TO_BLOG/src/data/dummy.md 4 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.にオプションなど記載あります。
package.json1{ 2 ... 3 "scripts":{ 4 ... 5 "textlint": "textlint --cache **/*.md", 6 ... 7 } 8 ... 9}
キャッシュファイルは当然生成されるのでgitignore
しましょう。
1.textlintcache
これで npm
スクリプトとして動かせます。
terminal1❯ npm run textlint 2 3> textlint 4> textlint --cache **/*.md 5 6 7PATH_TO_BLOG/src/data/dummy.md 8 1:3 error ら抜き言葉を使用しています。 no-dropping-the-ra
pre-commit の設定をする
これらをインストールし、husky
だけ初期設定します。
- okonet/lint-staged: 🚫💩 — Run linters on git staged files
- typicode/husky: Git hooks made easy 🐶 woof!
terminal1npm install husky -D 2npm pkg set scripts.prepare="husky install" 3npm run prepare 4npm install -D lint-staged 5npx husky add .husky/pre-commit "npx lint-staged"
常に動かすと重い+実行を忘れるため、良いことがないので pre-commit
に追加して動かしたいのです。
当然、全てに対してではなく、コミット前のステージングしたファイルだけです。そのためlint-staged
を使っています。また、以下のスクリプトは非常にシンプルにしていますが、本当は色々オプションを付けています。書き出したらキリもない・・・
- 以下のオプションを適宜使ってます(
--cache
などは付けて損ない) - CLI · Prettier
- Command Line Interface - ESLint - Pluggable JavaScript Linter
package.json1{ 2 ... 3 "lint-staged": { 4 "*.md": [ 5 "textlint --cache" 6 ], 7 "*.{js,jsx,ts,tsx,json,css,md}": [ 8 "eslint --fix", 9 "prettier --write" 10 ] 11 }, 12 ... 13}
"*.{js,jsx,ts,tsx,json,css,md}": [
としていますが、JS
系しか ESLint
で対応できないので以下のように設定しています(補足)。
.eslint-ignore1**/*.md 2**/*.css 3**/*.json
当然、以下のように分けても良いです。
package.json1{ 2 ... 3 "lint-staged": { 4 "*.md": [ 5 "textlint --cache" 6 ], 7 "*.{js,jsx,ts,tsx}": [ 8 "eslint --fix", 9 ], 10 "*.{js,jsx,ts,tsx,json,css,md}": [ 11 "prettier --write" 12 ] 13 }, 14 ... 15}
実際に動かすことで確かめます。あえてルールを無視するファイルであるdummy.md
を書きます。
dummy.md1食べれる
dummy.md
のら抜きをコミット出来なければ良いです
terminal1❯ git commit 2✔ Preparing lint-staged... 3❯ Running tasks for staged files... 4 ❯ package.json — 1 file 5 ❯ *.md — 1 file 6 ✖ textlint --cache [FAILED] 7 ❯ *.{js,jsx,ts,tsx,json,css,md} — 1 file 8 ✖ eslint --fix [KILLED] 9 ◼ prettier --write 10↓ Skipped because of errors from tasks. [SKIPPED] 11✔ Reverting to original state because of errors... 12✔ Cleaning up temporary files... 13 14✖ textlint --cache: 15 16PATH_TO_BLOG/src/data/dummy.md 17 1:3 error ら抜き言葉を使用しています。 no-dropping-the-ra 18 19✖ 1 problem (1 error, 0 warnings) 20 21 22✖ eslint --fix failed without output (KILLED). 23husky - pre-commit hook exited with code 1 (error)
「食べれる」→「食べられる」と修正します。
terminal1❯ git commit 2✔ Preparing lint-staged... 3❯ Running tasks for staged files... 4 ❯ package.json — 1 file 5 ✔ *.md — 1 file 6 ❯ *.{js,jsx,ts,tsx,json,css,md} — 1 file 7 ✔ eslint --fix 8 ⠸ prettier --write 9◼ Applying modifications from tasks... 10◼ Cleaning up temporary files...
これでコミットで動くぞ。
ルールを無視して良い箇所を指定する
本ブログでら抜き言葉の例を書くと、それもら抜き言葉のエラーを吐いてしまいダメです。ブログが公開できません。
ESLint と同様に指定した箇所を無視するようにします。
パッケージをインストールします。
terminal1npm install -D textlint-filter-rule-comments
設定ファイルを追記します。
.textlintrc1{ 2 ... 3 "filters": { 4 "comments": true 5 }, 6 ... 7}
本文にルールを適用します。
1<!-- textlint-disable --> 2 3```md:dummy.md 4食べれる 5``` 6 7<!-- textlint-enable --> 8 9<!-- textlint-disable --> 10 11「食べれる」→「食べられる」と修正します。 12 13<!-- textlint-enable -->
これでコミットできました。
terminal1✦ ❯ git commit 2✔ Preparing lint-staged... 3❯ Running tasks for staged files... 4 ❯ package.json — 1 file 5 ✔ *.md — 1 file 6 ❯ *.{js,jsx,ts,tsx,json,css,md} — 1 file 7 ✔ eslint --fix 8 ⠧ prettier --write 9◼ Applying modifications from tasks... 10◼ Cleaning up temporary files...
CI を設定する
特に難しいことはなく、ESLint と同様に静的解析を動かして落ちたらビルドが動かないだけです。
詳細は分量多いので載せませんが、develop
ブランチと、そのブランチへのプルリクエスト時のみ動かしてます。
JS / TS / JSX / TSX
などの静的解析 → テスト → ビルド →Slack への通知を行っています。
.github/workflows/build.yml1... 2- run: npm run textlint 3...
補足
VSCode
拡張機能は使わないです。
常に視覚的に見えるのはうざい(口悪い)ので、僕は入れません。
ただ、lint-staged
では過去のファイルに対してエラーを吐かないので、一応常に目に入るようにしたい人は VSCode
拡張機能を入れるのもありです。
プラグイン
たくさんあるので、随時追加しますが、自作したほうが良い気もしますね。
- textlint/textlint-filter-rule-comments: textlint filter rule that disables all rules between comments directive.
- textlint-ja/textlint-rule-preset-ja-technical-writing: 技術文書向けの textlint ルールプリセット
- textlint-ja/textlint-rule-preset-ja-spacing: スペース周りのスタイルを扱う textlint ルール集
おわりに
これでより良い、表記の整った文章に少しずつ変えていけるし、これからの文章は確実に良い表記になる。
あとは文章の構成能力を上げるなり、伝え方に注力しよう。