textlint 9.0.0をリリースしました。 textlint 9.0.0では@textlint/kernelという内部的に使うコアモジュールをTypeScriptで書き直したバージョンが使われています。

元々textlintはNode.jsで動くように作られたため、fsモジュールなどNode.jsに依存しています。 そのため、ブラウザなどで動かす場合などはビルド時に色々工夫しないと動きません。

この問題をどうにかするためには、textlintというモジュールからロジックやLint処理部分だけをNode.jsなどに依存しない純粋なJavaScriptとして切り出す必要があります。

アドホックに対応するならブラウザ向けのbundleをbrowser fieldなどで提供すれば終わりですが、長期的なことを考えるとモジュールを分けたほうが建設的です。

textlint organizationを見ると分かるようにtextlintはMarkdownパーサやトラバーサ、フォーマッターなどがモジュールとして各リポジトリに分けられていました。部品となるモジュールとリポジトリを1対1で分けると、Aをアップデートすると、Aに依存するBやCを更新するといったアップデートの連鎖反応が起きる問題があります。 また、新しいモジュールを切り出す心理的なコストがありました。

そのため、まずはtextlintを構成するモジュールを1つのリポジトリにまとめたmonorepo化をすることにしました。

monorepo

textlintではlernaを使ってmonorepo化しています。これにより、モジュール間の依存のアップデートが1つのPRにまとめられるなどアップデートの連鎖反応がある程度自動化できるメリットがあります。 また、新しいモジュールを追加するのも単純にディレクトリを切るだけなので心理的なコストは軽減されます。

一方、CIにかかる時間やpublishする際のコストは増加する傾向があります。 また、まだmonorepoにおけるリリースノートの戦略がイマイチ決まっていないという問題もあります。 これはalminとかtextlint-rule-preset-googleなど、他にもmonorepoをやっているのでいい方法を見出したいです。

@textlint/kernel

monorepo化がひとまずできたので、textlint 8.1.0textlintモジュールから@textlint/kernelというコアモジュールを切り出しました。(Coreという名前じゃないのは既にCoreという名前を使ったものがあったため) @textlint/kernelfsなどNode.js特有のものに依存してないような作りになっているので普通にwebpackやbrowserifyなどでビルドすれば動作します。

今回のtextlint 9.0.0ではさらにこの@textlint/kernelをTypeScriptに書き換えました。理由としては@textlint/kernelはロジックの塊であることと今後のリファクタリングのしやすさを考えたためです。

TL;DR: both Flow and TypeScript are pretty good, and conservatively either of them can prevent about 15% of the bugs that end up in committed code.
https://blog.acolyer.org/2017/09/19/to-type-or-not-to-type-quantifying-detectable-bugs-in-javascript/

JavaScriptに型注釈を加えることで15%程度バグを減らすことができるという話もありますが、IDEなどでリファクタリングがしやすくなるメリットは大きいです。(名前に依存した壊れたリファクタリングが発生しにくい)

JavaScriptからTypeScriptへの移行方法は次の記事で書いてるような手法を取っています。

まだ単に型を付けただけであったり、テストはTypeScriptになってなかったりします。 本体のtextlintの方もTypeScript化したいので興味がある人は次のIssueを参照してください。

また、まだルール側をTypeScriptで書きやすくなってはいないのでその辺もどうにかしたいですね。

今後

textlintはルールを気軽に作れるようにする土台を作ることが目的です。

今回色々リファクタリングして、@textlint/kernelの分離でLint以外への発展も少し見えてきています。Lintは入力に対して解答(正否)を出さないと行けないですが、textstatのように統計データを出したり、Glosserのようなフィードバックエンジンを作ってみたいです。

また、現在textlintに関係するリポジトリは200以上、textlintルールは100以上あります。 ただ、半分以上は自分が関連しているものなので、もっと属人性を解消して安定させたいです。

もっと安定して良くしていくために、textlint organizationのコラボレーターを募集しています。最初からコラボレーター(リリース権限とかもてる人)というのも互いに変ではあるので、まずはコントビューションしてくれる人を募集しています。

textlintではどういうところが足りてない、直せるのかなどについて簡単にまとめてみます。

textlintへのコントビューション

相談したいことがある場合はGitterに日本語のchatがあるのでそちらを使ってみてください。 (これどうやって直せばいいのとか?)

Gitter

textlintを直す

Contributing Guideにコミット方法やテスト方法など一通りのやり方は書いてあります。

ドキュメントを直す

  • 適当な英語が多いので修正歓迎

ドキュメントを追加する

  • ルールの作り方とかもっと具体例のドキュメント増やしたい
  • こういうのがわからないというIssueを立てるでもよさそう

コアを直す

  • textlintはmonorepoになっているのでtextlintに色々なパッケージが入っています。

label:"good for beginner"というラベルが付いてるものは、比較的やることがはっきりしています。 そのため最初のコントビューションとして手が出しやすいかもしれません。

また、textlintはあまりパフォーマンスの最適化がまだ行われていません。markdown-parserなど明らかに無駄な処理をしている部分があります。 一方、500以上のユニットテストや典型的なユースケースのExampleテスト、実際の文章を使ったIntegration testなどが書かれています。 そのため、壊れるとテストが落ちるはずなのでパフォーマンスの改善やリファクタリングなどはある程度し易いかもしれません。

TypeScriptで書きたいという人は、textlint本体もTypeScript化したり、型定義を整理したりすると良いかもしれません。

また、textlintをブラウザでもっと簡単に上手く動かしたいという人は次のIssueにどういうものがあると便利なのかやPOCを作ってみると良いかもしれません。

ルールを直す

  • textlintはデフォルトでルールをもっていません
  • そのためすべてのルールはプラグイン扱いです
  • ルール一覧はCollection of textlint rule · textlint/textlint Wikiにあります
  • 各ルールにPull RequestやIssueを立てるのがよさそうです
  • textlint-jaで管理している日本語専用のルールは、日本語が分かる人じゃないと使わないので、Issueなどは日本語で問題ないです

ルールを追加する

textlintのルールを置く場所には特に制限はありません。また自由にルールを書けます。

ただ一度作ったルールがメンテナンスされなくなってしまうのはもったないので、textlint-ruletextlint-jaMaintenance Guidelines for Organizationというガイドラインの元にしています。

人がボトルネックになることを避けるため、人が正しいことをできるように信用することという原則を元にしてリポジトリやnpmパッケージの権限を共有できるようにするという方針です。 そのため、textlintルールを作ったはいいけど置き場所や管理が不安というは、Organizationに参加してみるといいかもしれません。

それぞれoranizationも用意してあるので興味がある人は、@azu_reGitterで言ってもらえれば inviteします。

textlint@9.1.1でscoped moduleのサポートを拡張したのもこういったOrganizationでのルール管理のしやすさを改善するためでもあります。

{
  "rules": {
    "@textlint-rule/preset-google": true
  }
}

ルールを紹介する

自分が使っているルールや設定をブログなどで紹介するのも貢献です。

ツールを良くする

textlintのElectronアプリがありますがそこまで作り込まれてません。

textlintのルールをコマンド一発で作り始めることができるツールがあります。 コーパスを使ってルールをチェックしやすくするなどもっと色々な工夫をして、ルールづくりを簡単にできると嬉しいです。

ウェブサイト

textlintのウェブサイト兼オンラインデモとしてtextlint - pluggable linting tool for text and markdownがあります。

こちらもlabel:"good for beginner"のラベルがついたIssueがあります。

その他

textlintの直し方に簡単にコントビューション方法についてまとめています。