💅

styled-componentsでstylelintを使おう

2024/02/08に公開

業務でstylelintをstyled-componentsで使用する機会があったので備忘として書いておきます.

とりあえず導入する

  1. styled-components公式を参考にとりあえず導入
    yarn add -D stylelint \
    stylelint-config-standard \
    postcss-styled-syntax
    
  2. .stylelintrcを作成し,以下記述
    .stylelintrc
    {
      "extends": [
        "stylelint-config-standard",
      ],
      "customSyntax": "postcss-styled-syntax"
    }
    
  3. package.jsonにスクリプト追加
    package.json
    {
        "scripts": {
            "lint:style": "stylelint '**/*.ts'",
            "lint:style:fix": "stylelint --fix '**/*.ts'",
        },
    }
    
  4. これでスクリプトを実行すればstylelintが実行されるようになるはず.

ライブラリ追加する

今回はスタイルのプロパティをよしなにソートしてくれるライブラリを追加.
(stylelint-config-recess-order)

  1. インストール
yarn add -D stylelint-config-recess-order
  1. .stylelintrcに追記
.stylelintrc
{
  "extends": [
    "stylelint-config-standard",
+   "stylelint-config-recess-order", // ここ
  ],
  "customSyntax": "postcss-styled-syntax"
}

ルールをカスタマイズしていく

おそらく必須

ケースバイケース

  • no-empty-sourceを無効に
    • 空白のコンポーネントを許可するルール
    • 名前をつけて管理したい場合は許可してもいいかもしれない
  • stylelint-disablestylelint-enableは対の関係にする
    • 一度コメントアウトでdisableにしてしまうと再度enableにするまでルールが無効化されてしまう.
    • 上記の問題を解決するためにプラグインを自作して使用しています.
    • 以下のような挙動になります.
    // エラーになる例(stylelint-enableをつけていない)
    
    export const $Title = styled.div`
        /* stylelint-disable */
        color: red;
        font-size: 16px;
    `;
    
    // エラーにならない例(stylelint-enableをつけている)
    
    export const $Title = styled.div`
        /* stylelint-disable */
        color: red;
        font-size: 16px;
        /* stylelint-enable */
    `;
    
    // エラーにならない例(stylelint-enable-next-lineは次の行のみに適用されるためOK)
    export const $Title = styled.div`
        /* stylelint-disable-next-line */
        color: red;
        font-size: 16px;
    `;
    
コード
// eslint-disable-next-line @typescript-eslint/no-var-requires
const stylelint = require("stylelint");

const ruleName = "plugin/check-disable-enable-pair";
const messages = stylelint.utils.ruleMessages(ruleName, {
  disable:
    "Found an unmatched `stylelint-disable` comment. Ensure every `stylelint-disable` is followed by a corresponding `stylelint-enable` comment.",
});

const reportError = (comment, result) => {
  stylelint.utils.report({
    ruleName: ruleName,
    result: result,
    node: comment,
    message: messages.disable,
  });
};

const stylelintDisableRule = () => {
  return function (root, result) {
    let lastDisableComment = null;

    root.walkComments((comment) => {
      const text = comment.text.trim();

      if (/stylelint-disable-(next-line|line)/.test(text)) return;

      if (text.startsWith("stylelint-disable")) {
        // 既に無効化コメントがある場合はエラー
        if (lastDisableComment) reportError(lastDisableComment, result);
        lastDisableComment = comment;
      }

      // ペアが見つかった場合はリセット
      if (text.startsWith("stylelint-enable") && lastDisableComment) lastDisableComment = null;
    });

    // ファイルの最後に無効化コメントが残っている場合はエラー
    if (lastDisableComment) reportError(lastDisableComment, result);
  };
};

module.exports = stylelint.createPlugin(ruleName, stylelintDisableRule);
module.exports.ruleName = ruleName;
module.exports.messages = messages;
  • 他にも色々あるので見てみてください〜

まとめ

最終的な.stylelintrcはこんな感じです

.stylelintrc
{
  "extends": [
    "stylelint-config-standard",
    "stylelint-config-recess-order"
  ],
  "plugins": ["プラグインまでのパス/check-disable-enable-pair"],
  "rules": {
    "media-query-no-invalid": null,
    "no-empty-source": null,
    "plugin/check-disable-enable-pair": true
  },
  "customSyntax": "postcss-styled-syntax"
}

備考

v15ではPrettierとの併用が推奨されたためPrettierの拡張は必要なくなった
参考:https://stylelint.io/migration-guide/to-15/

おまけ:VSCodeでのStylelint設定

  1. VSCodeにて拡張機能をインストール
  2. settings.jsonに追記する
settings.json
{
    "stylelint.configFile": ".stylelintrcへの絶対パス",
    "stylelint.packageManager": "yarn",
    "stylelint.snippet": [
        "typescript"
    ],
    "stylelint.validate": [
        "typescript"
    ],
    "editor.codeActionsOnSave": {
        "source.fixAll.stylelint": true
    },
}
  1. これで保存すると自動修正されるはず.
SMARTCAMP Engineer Blog

Discussion