textlint 6.0リリース。--fixでの自動修正に対応
textlint 6.0をリリースしました。
モジュールとして使っている場合に、細かな破壊的な変更があります。
ツールとして使っている人は単純にnpm install textlint@6 -D
などでアップデートすれば動くと思います。
textlint自体については以下を見てください。
--fix
による自動修正の対応
5.5.3: –fix & –experimental supportで--fix
による自動修正機能を実験的にサポートしていました。
6.0では--fix
を--experimental
フラグなしで利用できるようになりました。
自動修正はルール側で対応が必要 かつ 原理的に自動修正が難しいルールもあると思うので、あくまで補助的な機能です。
Wikiにまとめてあるルールのうち、✔ fixableマークが付いてるものは対応しています。
対応しているルールをfixableルールと呼んでいて、以下のバッジをつけています。
現状では以下のようなルールが--fix
に対応しています。
- azu/textlint-rule-prh: textlint rule for prh.
- azu/textlint-rule-preset-JTF-style: JTF日本語標準スタイルガイド for textlint.
- azu/textlint-rule-spellcheck-tech-word
- io-monad/textlint-rule-common-misspellings: textlint rule to check common misspellings
- io-monad/textlint-rule-general-novel-style-ja: textlint rule to follow general style of Japanese novels
- nodaguti/textlint-rule-spellchecker: textlint rule to check spellings with native spellchecker
- nodaguti/textlint-rule-ginger: textlint rule to check your English grammar with Ginger Proofreading
fixableルールはprhと辞書を使った表記揺れの統一やJTF日本語標準スタイルガイドを使った表記の統一など、辞書ベースやスタイルの統一を簡単になるのが利点です。
逆に表現的なものをチェックするルールは自動修正が難しく、頑張ってもサジェストのような推敲支援になると思います。
- 東京Node学園祭2015で技術文書をソフトウェア開発する話をしてきた | Web Scratch
- 校正と推敲 | 技術文書をソフトウェア開発する話
- 編集は「自動化」されていく仕事なのか 編集者のためのイベント「編む庭 」レポ【前編】 - はてな編集部ブログ「編む庭」
textlintは校正支援として始めたツールなので、まだ推敲支援のような要素は入っていません。 以下のIssueでそのようなサジェストをどう扱うかについて話し合ってるので興味がある人は見てください。
また--fix
はread onlyなlintと違ってwrite処理であるため、バグを作りやすいです。
自分もリリースしてからあるルールでバグがあることに気づいたので、そういうのをテストする方法については以下で話し合っています。
使用してバグを見つけたら、
- それが特定のルールのバグであるならルールのリポジトリへ
- そうでなくて
textlint
のバグであるならtextlintへ
報告してください。
バグ報告の仕方については以下を参考にしてください。
Fixableルール
実際に--fix
による自動修正の例を見てみます。
このブログのリポジトリ対象にしてみます。
git clone https://github.com/efcl/efcl.github.io
cd efcl.github.io
次にtextlint
とfixableに対応してる3つのルール/プリセットをインストールします。
- azu/textlint-rule-preset-JTF-style: JTF日本語標準スタイルガイド for textlint.
- textlint-rule-spellcheck-tech-word
- io-monad/textlint-rule-common-misspellings: textlint rule to check common misspellings
npm i -D textlint textlint-rule-preset-jtf-style textlint-rule-spellcheck-tech-word textlint-rule-common-misspellings
インストールし終わったら、.textlintrc
にインストールしたルールを使うように設定します。
(--rule
や--preset
オプションでも指定できますが毎回やるのは面倒なので)
$(npm bin)/textlint --init
というコマンドを叩くと、空の.textlintrc
設定ファイルが作成されるので、編集して次のような設定をします。
{
"rules": {
"preset-jtf-style": true,
"spellcheck-tech-word": true,
"common-misspellings": true
}
}
この状態でチェックしたいファイルを指定すればtextlint
でLintすることができます。
自分の今まで書いてきた全記事のうちMarkdownをこのルールでLintしてみます。
$(npm bin)/textlint _posts/
...
✖ 6091 problems (6091 errors, 0 warnings)
✓ 5639 fixable problems.
Try to run: $ textlint --fix [file]
絶望的な数のエラーが表示されました…
デフォルトのformatterである-f stylish
または -f pretty-error
では、
Lintの結果にそのうち自動修正できるエラーの数を表示してくれます。
この数値は実際に修正できる数とは必ずしも一致しません。ルール間は独立しているので、重複や衝突が存在しているためです。基本的には衝突しないように修正を逐次的に処理していく形になります。
このエラーを実際に--fix
で修正してみたいと思います。
修正する前に、対象のファイルは必ず復元できるように、バックアップを取るかGitにコミットしておくなどしてください。
また、--dry-run
オプションを使うことで、実際にファイルの上書きはしないでどのような変更が行われるかを見ることができます。
変更を比較する場合は -f diff
でdiff表示をするformatterを利用すると分かりやすいです。
(--fix
は本当に逐次的に処理するので、ルールやファイルが多いと掛け算的に処理時間が増えます)
$(npm bin)/textlint _posts --fix --dry-run -f diff
# 実際に変更は反映しないでdiffだけをみる
....
✔ Fixed 5713 problems
✖ Remaining 73 problems
✖ 6091 problemsのうち✔ Fixed 5713 problemsが自動で修正することができます。
--dry-run
で問題ないのが確認できたら、--fix
のみにして上書き保存できます。
$(npm bin)/textlint _posts --fix
textlint v5からv6の変更点
textlint 5.0.0までの変更点については以前書いたので、5.0から6.0までにあった変更点を列挙してみます。
5.1.0
textlint-rule-preset
をサポートしました。
ルールプリセットは個別のルールをまとめたモジュールという位置づけです。
もちろん内蔵しているルール個別に設定を.textlintrc
に書くことができるので、
一つのルールに沢山のチェック機能を設けるよりも、個別のルールに分けてルールプリセットとして公開することを推奨しています。
5.2.0
textlint-formatter-<name>
のようなモジュールを--formatter <name>
という形で指定できるようになりました。
これを利用したカバレッジを出力するformatterを公開しています。
- azu/textlint-formatter-lcov: textlint formatter for lcov format
- azu/textlint-formatter-codecov: textlint formatter for codecov json.
- textlintで文章カバレッジレポートを継続的に見ていく | Web Scratch
formatterの作り方はドキュメントを見てください。
5.3.0
--stdin-filename
をサポートしました。
cat readme.md | textlint --format compact --stdin --stdin-filename readme.md
という感じで標準入力のテキストに対して擬似的な名前を付けることができます。 (拡張子に対応した種類のファイルとしてtextlintが処理するため)
この仕組はSublimeプラグインを作るのに使われています
5.4.0
.textlintrc
ファイルを作成する--init
オプションが追加されました。
textlint --init
で空の.textlintrc
ファイルを作成してくれます。
まだ色々改良の余地があるので興味がある人は以下のIssueを見てください。
5.5.3
--fix
と--experimental
を実験的にサポートしました。
ここで実験的に追加した--fix
は6.0.0で正式サポートとなります。
5.6.0
ルール開発者向けにRuleError
がindex
プロパティをサポートしました。
var ruleError = new context.RuleError("Found rule error", { index: paddingIndex });
正確なエラーの位置を簡単に指定できます。
今まで通り、column
とline
の組み合わせでも問題ないですが、column
単独の指定はindex
に書き換える事を推奨しています。
- textlint/rule.md at master · textlint/textlint
- textlint/failed-to-load-textlints-module.md at master · textlint/textlint
textlint-testerでテストしている場合は、column
単独の場合には警告を出してくれます。
5.7.0
5.7.0では一部formatterがエラーとそのエラーが自動修正できるかを出すようになりました。
6.0
6.0では
--dry-run
のサポート(--fix
と組み合わせて使います)--fix
からexperimentalフラグが外れました--fix
向けのformatterとして-f diff
を追加しました
モジュールとして使う場合に関連するものとして
TextLintEngine#setRulesBaseDirectory
が削除されましたTextFixEngine
が追加されました--fix
における処理を扱うEngineです
TextLintCore#setupProcessors
が追加されました- Processorを設定するAPIです
また内部をかなりリファクタリングして、
- CLI
- Engine
- Core
の役割と関心を分離してディレクトリなどを切るようになりました。 詳しくは以下のドキュメントに書かれています。
結構長くなりましたが、5.0.0〜6.0.0の変更点は以上です。 Breaking Changeはほとんどのユーザには関係ないものだと思います(実際使ってるコードはGitHub上にはなかった)
その他
Chrome拡張として動くので、Node.jsを入れなくてもブラウザにインストールしてGUIで設定できるので簡単に使うことができます。
Atomプラグインとしてlinter-textlintを使う場合は上記のリポジトリが参考になるかもしれません。
開発メモ
--fix
は5.5から使えたのですが、色々APIデザインを変更する可能性があったのでexperimentalフラグを付けてリリースしました。
浅いイテレーションをするには
- 本体機能をテストしてもらいたいならbetaをとにかく出す
- プラグインに関係するエコシステム的な機能を試したいならexperimentalフラグ付きで出す
- プラグイン側は最新の本体でしか動かない変更を入れるならメジャーアップデート
- 本体バージョンとプラグインの参照するバージョンがズレているとユーザーはハマります
- なのでメジャーアップデートとするのが無難です
- プラグイン側が特定バージョン以降に依存するならpeerDependenciesを付ける
- npmのbetaとGitHubのprereleaseを使う
npm publish --tag beta
するalisを使っています- npm version publish alias - https://efcl.info/2015/04/08/npm-publish-pattern/
- npm publishのパターン | Web Scratch
- フラグつき機能は、次のメジャーアップデートで外す
- testライブラリを作りdeprecatedはプラグイン作者に通知
- テスト中はガンガン例外を投げて伝える
- textlintはtextlint-tester経由の実行時のみ例外を投げるUtilを持っています。
- throw-log.js
- 本体とプラグインが同時にnpmのbetaになると辛い
- βはsemverで
>=
のような指定ができなくて、直書きする事になって辛いです
- βはsemverで
- experimentalフラグ付きで本体はstableリリースして、プラグインはstableな本体に依存させたbetaを出す
- プラグインがstableリリースする際はメジャーアップデート+peerDependenciesにする
- この辺が
--experimental
フラグを作った理由です
- この辺が
課題としては
- 本体のBreaking Changeに依存したプラグインの変更をうまく扱う方法がない
- なので本体のBreaking Changeはなるべく小さく、単独でリリースする
- プラグインがすぐに追従できるような変更の粒度を考える
という感じになっています。
お知らせ欄
JavaScript Primerの書籍版がAmazonで購入できます。
JavaScriptに関する最新情報は週一でJSer.infoを更新しています。
GitHub Sponsorsでの支援を募集しています。