stylelintのPluginをTypeScriptで作る

ESLint ができるなら stylelint はどうだろうと思って作ってみた。
結果、現状そこまで TS と親和性高くないけど、作れるっちゃ作れるといった感じ。

作ったものはこれ

  • typescript
  • ts-jest
  • ts-node
  • jest-preset-stylelint

を使用した。

stylelint の plugin を作る簡単な構成

これは TS 関係ないが、基本事項として。
stylelint の提供するcreatePluginを作ることで plugin を作成することができる。
そのため、

  • rule 関数
  • ruleName
    の2つを渡してあげれば作れる。

ルールが複数ある場合は、配列にすることが可能。
plugin の場合、ruleName には、

const ruleName = "plugin/foo-bar";

のように、plugin 名 + rule 名をつける必要がある。

大まかな流れ

commonjs にビルドする

stylelint は commonjs 形式でプラグインを受け入れるので、target は commonjs にする

@types/stylelint を使用する

実は stylelint の types は、存在はするがメンテナンスはされていない
なので、ところどころおかしい方があると思うので、そこは自分で拡張したほうがいい。
頑張って開発しよう!!!

stylelint の issue を見る限り、コアメンバーは types を core に取り込むことに乗り気ではない Add Support for TypeScript · Issue #2444 · stylelint/stylelint · GitHub

stylelint は stylelint 自身の開発のために、JSDocs から types を生成している。
これは現在公開用の types ではないが、将来的には plugin 開発者のための types にしようとしている。
Create TypeScript definitions · Issue #4399 · stylelint/stylelint · GitHub

test を書く

最近jest-preset-stylelintが最新の stylelint のバージョンに対応するようにアップデートされ、stylleint の rule のテストを jest で書けるようになった。
jest の preset として使うので、実際に使うときは@ts-ignoreとかで ts エラーを無視して使おう。

公式サイトでも test に jest-preset-typescript を使おうってなってた。めでたい。Writing plugins · stylelint

リリース

流れとしてはこんな感じ

TS 対応させるためにいろいろやったところ

NamespaceCreator

TS あんまり関係ないけど。
ruleName を @hogehoge/rule-nameってするために、都度@hogehogeってかくのもめんどくさいので、namespace-creatorという高階関数作った。
namespaceこうやって使えば、
あとはnamespace('rule-name')ってすれば、@tyankatsu0105/rule-nameってなるので便利。

pluginCreator

これも TS 関係ないが。
createPlugin を使って rule の公開ができるが、

import noHoge from "./rules/no-hoge";

export const rules = {
  "no-hoge": noHoge,
};

ってやって、rules を渡せばいい感じに rule の公開をしてくれるplugin-creatorを作った。
pluginCreator(rules)

[
  {
    ruleName: "@tyankatsu0105/no-hoge",
    rule: [Function: rule] {
      ruleName: '@tyankatsu0105/no-hoge',
      messages: [Object]
    }
  },
];

って作ってくれるので便利。

RuleCreator

typescript-eslint の RuleCreatorを真似てrule-creatorを作った。
createRule を生成して、こんなふうに使った
utils.report に ruleName と message を入れないとだめなので、どっちにしろ rule 定義ファイル内でこの2つを生成しないとだめなのがちょっときつい。

今気がついたが、高階関数である必要がない。

testRule

jest-preset-stylelint は jest の preset で、jest の global に testRule というテスト用の関数を使用可能にする。
ESLint はエラー消せるが、TS のエラーの消し方が@ts-ignore以外分からず、これを書くのも気持ち嫌なので、test-ruleを作った。
これを test ファイル内で import して使えば、rule のテストが可能。
plugins は、plugin として rule を export する対象を指す。

終わりに

ちょっとまだ TS で stylelint の plugin 書くのはしんどいので、やるなら、stylelint が types の公開に向けて作業しているので、手伝うと良さそう。