eslint-plugin-smarthr 6.21.1 → 6.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +3 -2
  3. package/package.json +1 -1
  4. package/rules/autofixer-smarthr-ui-migration/DEVELOPER.md +4 -4
  5. package/rules/autofixer-smarthr-ui-migration/README.md +2 -0
  6. package/rules/autofixer-smarthr-ui-migration/index.js +21 -0
  7. package/rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/README.md +47 -0
  8. package/rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/REFERENCE.md +132 -0
  9. package/rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/index.js +54 -0
  10. package/rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/test.js +142 -0
  11. package/rules/autofixer-smarthr-ui-migration/versions/v96-to-v97/README.md +96 -0
  12. package/rules/autofixer-smarthr-ui-migration/versions/v96-to-v97/index.js +56 -0
  13. package/rules/autofixer-smarthr-ui-migration/versions/v96-to-v97/test.js +137 -0
  14. package/rules/best-practice-for-reduce-redundant-calls/README.md +460 -0
  15. package/rules/best-practice-for-reduce-redundant-calls/index.js +623 -0
  16. package/rules/best-practice-for-unstable-dependencies/README.md +74 -0
  17. package/rules/best-practice-for-unstable-dependencies/index.js +64 -12
  18. package/rules/require-i18n-translation-sync/README.md +19 -0
  19. package/rules/require-i18n-translation-sync/index.js +24 -0
  20. package/test/autofixer-smarthr-ui-migration.js +20 -6
  21. package/test/best-practice-for-reduce-redundant-calls.js +1195 -0
  22. package/test/best-practice-for-unstable-dependencies.js +125 -0
  23. package/test/require-i18n-translation-sync.js +35 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,22 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [6.22.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.21.2...eslint-plugin-smarthr-v6.22.0) (2026-07-02)
6
+
7
+
8
+ ### Features
9
+
10
+ * autofixer-smarthr-ui-migration v95-to-v96, v96-to-v97 対応 ([#1442](https://github.com/kufu/tamatebako/issues/1442)) ([d70787b](https://github.com/kufu/tamatebako/commit/d70787bc6961b0f65b6cc78506fab92707ce3f90))
11
+ * best-practice-for-reduce-redundant-calls ルールを追加 ([#1440](https://github.com/kufu/tamatebako/issues/1440)) ([0564d24](https://github.com/kufu/tamatebako/commit/0564d24fa5de3b9f812d23c7396411e064604234))
12
+ * best-practice-for-unstable-dependenciesに正規表現パターンとカスタムメッセージを追加 ([#1424](https://github.com/kufu/tamatebako/issues/1424)) ([9ed3f1f](https://github.com/kufu/tamatebako/commit/9ed3f1fac878b7f0f37c5a1f3db1b66d30d507c9))
13
+
14
+ ## [6.21.2](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.21.1...eslint-plugin-smarthr-v6.21.2) (2026-06-30)
15
+
16
+
17
+ ### Bug Fixes
18
+
19
+ * require-i18n-translation-syncでsatisfies演算子に対応 ([#1415](https://github.com/kufu/tamatebako/issues/1415)) ([d0eb87a](https://github.com/kufu/tamatebako/commit/d0eb87a1616c63145499b8adc9fc20d5f6f8c5b9))
20
+
5
21
  ## [6.21.1](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.21.0...eslint-plugin-smarthr-v6.21.1) (2026-06-22)
6
22
 
7
23
 
package/README.md CHANGED
@@ -26,12 +26,13 @@
26
26
  - [best-practice-for-date](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-date)
27
27
  - [best-practice-for-default-props](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-default-props)
28
28
  - [best-practice-for-interactive-element](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-interactive-element)
29
- - [best-practice-for-lazy-variable](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-lazy-variable)
30
- - [best-practice-for-no-unnecessary-variable](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-no-unnecessary-variable)
31
29
  - [best-practice-for-layouts](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts)
30
+ - [best-practice-for-lazy-variable](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-lazy-variable)
32
31
  - [best-practice-for-nested-attributes-array-index](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-nested-attributes-array-index)
32
+ - [best-practice-for-no-unnecessary-variable](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-no-unnecessary-variable)
33
33
  - [best-practice-for-optional-chaining](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-optional-chaining)
34
34
  - [best-practice-for-prohibit-import-smarthr-ui-local](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-prohibit-import-smarthr-ui-local)
35
+ - [best-practice-for-reduce-redundant-calls](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-reduce-redundant-calls)
35
36
  - [best-practice-for-remote-trigger-dialog](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-remote-trigger-dialog)
36
37
  - [best-practice-for-response-message](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-response-message)
37
38
  - [best-practice-for-rest-parameters](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-rest-parameters)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-smarthr",
3
- "version": "6.21.1",
3
+ "version": "6.22.0",
4
4
  "author": "SmartHR",
5
5
  "license": "MIT",
6
6
  "description": "A sharable ESLint plugin for SmartHR",
@@ -66,10 +66,10 @@ autofixer-smarthr-ui-migrationルールに新しいバージョン(v[XX]→v[Y
66
66
  ## 参考にするファイル
67
67
 
68
68
  必ず以下のファイルを読んで、実装パターンを踏襲してください(最新のversionディレクトリを参照):
69
- - rules/autofixer-smarthr-ui-migration/versions/v94-to-v95/REFERENCE.md(実装パターンの詳細説明)
70
- - rules/autofixer-smarthr-ui-migration/versions/v94-to-v95/index.js(実装例)
71
- - rules/autofixer-smarthr-ui-migration/versions/v94-to-v95/README.md(ユーザー向け移行ガイド)
72
- - rules/autofixer-smarthr-ui-migration/versions/v94-to-v95/test.js(テストケース)
69
+ - rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/REFERENCE.md(実装パターンの詳細説明)
70
+ - rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/index.js(実装例)
71
+ - rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/README.md(ユーザー向け移行ガイド)
72
+ - rules/autofixer-smarthr-ui-migration/versions/v95-to-v96/test.js(テストケース)
73
73
  - test/autofixer-smarthr-ui-migration.js(メインテスト)
74
74
  - libs/common.js(rootPathの取得、tsconfig.jsonのpaths設定読み込み)
75
75
 
@@ -196,6 +196,8 @@ export const ActionDialog = (props) => <div>{props.children}</div>
196
196
  | `92` → `93` | [移行ガイド](./versions/v92-to-v93/README.md) |
197
197
  | `93` → `94` | [移行ガイド](./versions/v93-to-v94/README.md) |
198
198
  | `94` → `95` | [移行ガイド](./versions/v94-to-v95/README.md) |
199
+ | `95` → `96` | [移行ガイド](./versions/v95-to-v96/README.md) |
200
+ | `96` → `97` | [移行ガイド](./versions/v96-to-v97/README.md)(検出のみ) |
199
201
 
200
202
  ## 使用方法
201
203
 
@@ -20,6 +20,8 @@ const v91ToV92 = require('./versions/v91-to-v92/index')
20
20
  const v92ToV93 = require('./versions/v92-to-v93/index')
21
21
  const v93ToV94 = require('./versions/v93-to-v94/index')
22
22
  const v94ToV95 = require('./versions/v94-to-v95/index')
23
+ const v95ToV96 = require('./versions/v95-to-v96/index')
24
+ const v96ToV97 = require('./versions/v96-to-v97/index')
23
25
 
24
26
  // サポートしているバージョン間の移行モジュール
25
27
  const VERSION_MODULES = {
@@ -28,6 +30,8 @@ const VERSION_MODULES = {
28
30
  'v92-v93': v92ToV93,
29
31
  'v93-v94': v93ToV94,
30
32
  'v94-v95': v94ToV95,
33
+ 'v95-v96': v95ToV96,
34
+ 'v96-v97': v96ToV97,
31
35
  }
32
36
 
33
37
  module.exports = {
@@ -64,6 +68,8 @@ module.exports = {
64
68
  ...v92ToV93.messages,
65
69
  ...v93ToV94.messages,
66
70
  ...v94ToV95.messages,
71
+ ...v95ToV96.messages,
72
+ ...v96ToV97.messages,
67
73
  },
68
74
  },
69
75
  create(context) {
@@ -200,6 +206,21 @@ function getMigrationPath(from, to) {
200
206
  }
201
207
  }
202
208
 
209
+ // v96→v97は検出のみのルール(手動対応必須)のため、他のバージョンとの一気実行を禁止
210
+ // v95→v96(自動修正)とv96→v97(検出のみ)を混在させると、エラーが消えず混乱する
211
+ if (path.includes('v95-v96') && path.includes('v96-v97')) {
212
+ return {
213
+ path,
214
+ skipped,
215
+ conflict: true,
216
+ conflictData: {
217
+ from,
218
+ to,
219
+ middle: '96',
220
+ },
221
+ }
222
+ }
223
+
203
224
  return { path, skipped }
204
225
  }
205
226
 
@@ -0,0 +1,47 @@
1
+ # smarthr-ui v95 → v96 移行ガイド
2
+
3
+ このドキュメントは、smarthr-ui を v95 から v96 にアップグレードする際の破壊的変更と対処方法を説明します。
4
+
5
+ ## 破壊的変更
6
+
7
+ ### Chip: size 属性の値が "s" から "S" に変更
8
+
9
+ **変更内容:**
10
+ `Chip` コンポーネントの `size` 属性の値が小文字の `"s"` から大文字の `"S"` に変更されました。
11
+
12
+ **Before (v95):**
13
+ ```jsx
14
+ <Chip size="s">label</Chip>
15
+ ```
16
+
17
+ **After (v96):**
18
+ ```jsx
19
+ <Chip size="S">label</Chip>
20
+ ```
21
+
22
+ **自動修正:**
23
+ このルールは自動修正に対応しています。ESLintの`--fix`オプションを使用することで、自動的に変換されます。
24
+
25
+ ```bash
26
+ eslint --fix .
27
+ ```
28
+
29
+ **対象:**
30
+ - 文字列リテラル `"s"` のみが対象です
31
+ - 動的な値(変数など)は検出されません
32
+ - `Chip` で終わるコンポーネント名(例: `CustomChip`, `MyChip`)も対象です
33
+
34
+ ```jsx
35
+ // 自動修正される
36
+ <Chip size="s">label</Chip>
37
+ <CustomChip size="s">label</CustomChip> // ラップコンポーネントも対象
38
+
39
+ // 検出されない(手動で対応が必要)
40
+ <Chip size={dynamicSize}>label</Chip>
41
+ <Chip size={SIZES.SMALL}>label</Chip>
42
+ <ChipContainer size="s" /> // "Chip"で終わらない
43
+ ```
44
+
45
+ ## 参考リンク
46
+
47
+ - [smarthr-ui v96.0.0 Release Notes](https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v96.0.0)
@@ -0,0 +1,132 @@
1
+ # v95-to-v96 実装リファレンス
2
+
3
+ このドキュメントは、v95-to-v96移行ルールの実装パターンとトラブルシューティングをまとめた開発者向けリファレンスです。
4
+
5
+ ## 実装パターン
6
+
7
+ ### 1. JSX属性値の文字列置換
8
+
9
+ **ユースケース:** Chip の size 属性を "s" から "S" に変更
10
+
11
+ **実装例:**
12
+ ```javascript
13
+ 'JSXOpeningElement[name.name=/Chip$/] > JSXAttribute[name.name="size"][value.type="Literal"][value.value="s"]'(node) {
14
+ context.report({
15
+ node,
16
+ messageId: 'migrateChipSize',
17
+ data: { to: TARGET_VERSION },
18
+ fix(fixer) {
19
+ // "s" → "S" に置換
20
+ return fixer.replaceText(node.value, '"S"')
21
+ },
22
+ })
23
+ }
24
+ ```
25
+
26
+ **ポイント:**
27
+ - セレクタで条件をすべて絞り込む(関数内チェック不要)
28
+ - `name.name=/Chip$/`: Chipで終わるコンポーネント名(CustomChip等も対象)
29
+ - `[value.type="Literal"][value.value="s"]`: 文字列リテラル "s" のみ
30
+ - `fixer.replaceText()` で値全体を置換する
31
+
32
+ **検出対象:**
33
+ ```jsx
34
+ <Chip size="s">label</Chip> // ✅ 検出される
35
+ ```
36
+
37
+ **検出対象外:**
38
+ ```jsx
39
+ <Chip size={dynamicSize}>label</Chip> // ❌ 動的な値
40
+ <Chip size={"s"}>label</Chip> // ❌ JSX式
41
+ <OtherComponent size="s" /> // ❌ 他のコンポーネント
42
+ ```
43
+
44
+ ## テストパターン
45
+
46
+ ### 基本的なテスト構成
47
+
48
+ ```javascript
49
+ const v95ToV96Options = [{ from: '95', to: '96' }]
50
+
51
+ const valid = [
52
+ // 既に正しい値
53
+ { code: '<Chip size="S">label</Chip>', options: v95ToV96Options },
54
+
55
+ // 動的な値(検出対象外)
56
+ { code: '<Chip size={dynamicSize}>label</Chip>', options: v95ToV96Options },
57
+ ]
58
+
59
+ const invalid = [
60
+ {
61
+ code: '<Chip size="s">label</Chip>',
62
+ output: '<Chip size="S">label</Chip>',
63
+ options: v95ToV96Options,
64
+ errors: [
65
+ {
66
+ messageId: 'migrateChipSize',
67
+ data: { to: 'v96' },
68
+ },
69
+ ],
70
+ },
71
+ ]
72
+ ```
73
+
74
+ ## トラブルシューティング
75
+
76
+ ### JSX式内の文字列が検出されない
77
+
78
+ **問題:**
79
+ ```jsx
80
+ <Chip size={"s"}>label</Chip> // 検出されない
81
+ ```
82
+
83
+ **原因:**
84
+ JSX式(`{}`)内の文字列は `JSXExpressionContainer > Literal` という構造になる。
85
+
86
+ **対処:**
87
+ 現在の実装では文字列リテラル(`size="s"`)のみを対象としています。JSX式内の文字列も対象にする場合は、以下のように拡張できます:
88
+
89
+ ```javascript
90
+ 'JSXOpeningElement[name.name="Chip"] > JSXAttribute[name.name="size"]'(node) {
91
+ const value = node.value
92
+
93
+ // 文字列リテラル: size="s"
94
+ if (value && value.type === 'Literal' && value.value === 's') {
95
+ // 修正処理
96
+ }
97
+
98
+ // JSX式: size={"s"}
99
+ if (value && value.type === 'JSXExpressionContainer') {
100
+ const expr = value.expression
101
+ if (expr.type === 'Literal' && expr.value === 's') {
102
+ // 修正処理
103
+ }
104
+ }
105
+ }
106
+ ```
107
+
108
+ ただし、実用上は文字列リテラルのみで十分なケースが多いです。
109
+
110
+ ## 参考情報
111
+
112
+ ### AST構造
113
+
114
+ **文字列リテラル:** `size="s"`
115
+ ```
116
+ JSXAttribute
117
+ ├── name: JSXIdentifier (name: "size")
118
+ └── value: Literal (value: "s")
119
+ ```
120
+
121
+ **JSX式:** `size={"s"}`
122
+ ```
123
+ JSXAttribute
124
+ ├── name: JSXIdentifier (name: "size")
125
+ └── value: JSXExpressionContainer
126
+ └── expression: Literal (value: "s")
127
+ ```
128
+
129
+ ### 関連ドキュメント
130
+
131
+ - [ESLint AST Explorer](https://astexplorer.net/)
132
+ - [smarthr-ui v96.0.0 Release Notes](https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v96.0.0)
@@ -0,0 +1,54 @@
1
+ /**
2
+ * smarthr-ui v95 → v96 移行ルール
3
+ *
4
+ * v96での破壊的変更に対応する自動修正を提供します。
5
+ *
6
+ * 対応する破壊的変更:
7
+ * 1. Chip の size 属性: "s" → "S"
8
+ *
9
+ * 参考: https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v96.0.0
10
+ */
11
+
12
+ const { setupSmarthrUiAliasOptions } = require('../../helpers')
13
+
14
+ // ============================================================
15
+ // 定数定義
16
+ // ============================================================
17
+
18
+ // v96を示す定数(メッセージで使用)
19
+ const TARGET_VERSION = 'v96'
20
+
21
+ // ============================================================
22
+ // モジュールエクスポート
23
+ // ============================================================
24
+
25
+ module.exports = {
26
+ messages: {
27
+ migrateChipSize: 'smarthr-ui {{to}} では Chip の size 属性が "s" から "S" に変更されました',
28
+ },
29
+
30
+ createCheckers(context, sourceCode, options = {}) {
31
+ const { validSources, isAliasFile, filename } = setupSmarthrUiAliasOptions(context, options)
32
+
33
+ const checkers = {
34
+ // ============================================================
35
+ // 1. Chip の size 属性: "s" → "S"
36
+ // Chipで終わるコンポーネント(CustomChip等のラップコンポーネント)も対象
37
+ // ============================================================
38
+
39
+ 'JSXOpeningElement[name.name=/Chip$/] > JSXAttribute[name.name="size"][value.type="Literal"][value.value="s"]'(node) {
40
+ context.report({
41
+ node,
42
+ messageId: 'migrateChipSize',
43
+ data: { to: TARGET_VERSION },
44
+ fix(fixer) {
45
+ // "s" → "S" に置換
46
+ return fixer.replaceText(node.value, '"S"')
47
+ },
48
+ })
49
+ },
50
+ }
51
+
52
+ return checkers
53
+ },
54
+ }
@@ -0,0 +1,142 @@
1
+ /**
2
+ * smarthr-ui v95 → v96 移行ルール テストケース
3
+ */
4
+
5
+ const v95ToV96Options = [{ from: '95', to: '96' }]
6
+
7
+ // ============================================================
8
+ // validテストケース(エラーにならないコード)
9
+ // ============================================================
10
+
11
+ const valid = [
12
+ // size属性なし
13
+ { code: '<Chip>label</Chip>', options: v95ToV96Options },
14
+
15
+ // 既に "S" を使用
16
+ { code: '<Chip size="S">label</Chip>', options: v95ToV96Options },
17
+
18
+ // 他のサイズ値
19
+ { code: '<Chip size="m">label</Chip>', options: v95ToV96Options },
20
+
21
+ // 動的な値
22
+ { code: '<Chip size={dynamicSize}>label</Chip>', options: v95ToV96Options },
23
+ { code: '<Chip size={SIZES.SMALL}>label</Chip>', options: v95ToV96Options },
24
+
25
+ // JSX式での "s"(文字列リテラルではない)
26
+ { code: '<Chip size={"s"}>label</Chip>', options: v95ToV96Options },
27
+
28
+ // 対象外のコンポーネント(Chipで終わらない)
29
+ { code: '<OtherComponent size="s" />', options: v95ToV96Options },
30
+ { code: '<ChipContainer size="s" />', options: v95ToV96Options },
31
+ ]
32
+
33
+ // ============================================================
34
+ // invalidテストケース(エラーになり、自動修正されるコード)
35
+ // ============================================================
36
+
37
+ const invalid = [
38
+ // ============================================================
39
+ // Chip の size 属性: "s" → "S"
40
+ // ============================================================
41
+
42
+ // 基本的な使用例
43
+ {
44
+ code: '<Chip size="s">label</Chip>',
45
+ output: '<Chip size="S">label</Chip>',
46
+ options: v95ToV96Options,
47
+ errors: [
48
+ {
49
+ messageId: 'migrateChipSize',
50
+ data: { to: 'v96' },
51
+ },
52
+ ],
53
+ },
54
+
55
+ // セルフクロージングタグ
56
+ {
57
+ code: '<Chip size="s" />',
58
+ output: '<Chip size="S" />',
59
+ options: v95ToV96Options,
60
+ errors: [
61
+ {
62
+ messageId: 'migrateChipSize',
63
+ data: { to: 'v96' },
64
+ },
65
+ ],
66
+ },
67
+
68
+ // 複数の属性がある場合
69
+ {
70
+ code: '<Chip size="s" disabled>label</Chip>',
71
+ output: '<Chip size="S" disabled>label</Chip>',
72
+ options: v95ToV96Options,
73
+ errors: [
74
+ {
75
+ messageId: 'migrateChipSize',
76
+ data: { to: 'v96' },
77
+ },
78
+ ],
79
+ },
80
+
81
+ // spread属性と組み合わせ
82
+ {
83
+ code: '<Chip {...props} size="s">label</Chip>',
84
+ output: '<Chip {...props} size="S">label</Chip>',
85
+ options: v95ToV96Options,
86
+ errors: [
87
+ {
88
+ messageId: 'migrateChipSize',
89
+ data: { to: 'v96' },
90
+ },
91
+ ],
92
+ },
93
+
94
+ // 複数行
95
+ {
96
+ code: `<Chip
97
+ size="s"
98
+ disabled
99
+ >
100
+ label
101
+ </Chip>`,
102
+ output: `<Chip
103
+ size="S"
104
+ disabled
105
+ >
106
+ label
107
+ </Chip>`,
108
+ options: v95ToV96Options,
109
+ errors: [
110
+ {
111
+ messageId: 'migrateChipSize',
112
+ data: { to: 'v96' },
113
+ },
114
+ ],
115
+ },
116
+
117
+ // ラップコンポーネント(Chipで終わる名前)
118
+ {
119
+ code: '<CustomChip size="s">label</CustomChip>',
120
+ output: '<CustomChip size="S">label</CustomChip>',
121
+ options: v95ToV96Options,
122
+ errors: [
123
+ {
124
+ messageId: 'migrateChipSize',
125
+ data: { to: 'v96' },
126
+ },
127
+ ],
128
+ },
129
+ {
130
+ code: '<MyChip size="s" />',
131
+ output: '<MyChip size="S" />',
132
+ options: v95ToV96Options,
133
+ errors: [
134
+ {
135
+ messageId: 'migrateChipSize',
136
+ data: { to: 'v96' },
137
+ },
138
+ ],
139
+ },
140
+ ]
141
+
142
+ module.exports = { valid, invalid }
@@ -0,0 +1,96 @@
1
+ # smarthr-ui v96 → v97 移行ガイド
2
+
3
+ このドキュメントは、smarthr-ui を v96 から v97 にアップグレードする際の破壊的変更と対処方法を説明します。
4
+
5
+ ## 破壊的変更
6
+
7
+ ### TabItem: onClick の型が変更
8
+
9
+ **変更内容:**
10
+ `TabItem` コンポーネントの `onClick` プロパティの型が、カスタムハンドラから標準的なイベントハンドラに変更されました。
11
+
12
+ **Before (v96):**
13
+ ```tsx
14
+ <TabItem onClick={(tabId: string) => console.log(tabId)} />
15
+ ```
16
+
17
+ **After (v97):**
18
+ ```tsx
19
+ <TabItem onClick={(e: MouseEvent<HTMLButtonElement>) => console.log(e.currentTarget.value)} />
20
+ ```
21
+
22
+ **変更の理由:**
23
+ - より標準的なイベントハンドラの型に統一
24
+ - ESLint ルール `smarthr/best-practice-for-unstable-dependencies` との互換性向上
25
+ - `useCallback` の依存配列を安定化
26
+
27
+ **自動修正について:**
28
+ この変更は**自動修正に対応していません**。以下の理由により、手動での対応が必要です:
29
+
30
+ - 引数名が可変(`tabId`, `id`, `value` など)
31
+ - 関数本体内での使用箇所の特定が複雑
32
+ - 変数代入、関数呼び出し、オブジェクトプロパティなど多様な使用パターン
33
+
34
+ **手動対応の手順:**
35
+
36
+ 1. **引数を `e` に変更**
37
+ ```tsx
38
+ // Before
39
+ onClick={(tabId) => handleClick(tabId)}
40
+
41
+ // After
42
+ onClick={(e) => handleClick(e.currentTarget.value)}
43
+ ```
44
+
45
+ 2. **引数の使用箇所を `e.currentTarget.value` に置き換え**
46
+ ```tsx
47
+ // Before
48
+ onClick={(id) => {
49
+ console.log(id)
50
+ setActiveTab(id)
51
+ }}
52
+
53
+ // After
54
+ onClick={(e) => {
55
+ const id = e.currentTarget.value
56
+ console.log(id)
57
+ setActiveTab(id)
58
+ }}
59
+ ```
60
+
61
+ 3. **TypeScript の型エラーを確認**
62
+ ```tsx
63
+ // 型定義を明示的に指定する場合
64
+ onClick={(e: MouseEvent<HTMLButtonElement>) => {
65
+ // 処理
66
+ }}
67
+ ```
68
+
69
+ ## 検出方法
70
+
71
+ このルールは `TabItem` コンポーネントに `onClick` プロパティがある箇所を検出し、手動対応を促すエラーを表示します。
72
+
73
+ ```bash
74
+ # ESLintでエラーを確認
75
+ eslint .
76
+ ```
77
+
78
+ **重要な注意事項:**
79
+ - `--fix` オプションを使用しても自動修正されません。エラーメッセージに従って手動で修正してください。
80
+ - **このエラーは手動で修正しても消えません**。`TabItem` に `onClick` がある限り検出され続けます。
81
+ - すべての対応が完了したら、ESLint設定から `{ from: "96", to: "97" }` の設定を削除してください。
82
+
83
+ ```javascript
84
+ // .eslintrc.js または eslint.config.js
85
+ {
86
+ rules: {
87
+ // 対応完了後は削除またはコメントアウト
88
+ // 'smarthr/autofixer-smarthr-ui-migration': ['error', { from: '96', to: '97' }],
89
+ }
90
+ }
91
+ ```
92
+
93
+ ## 参考リンク
94
+
95
+ - [smarthr-ui v97.0.0 Release Notes](https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v97.0.0)
96
+ - [PR #6421: onClickの型をイベントハンドラに変更](https://github.com/kufu/smarthr-ui/pull/6421)
@@ -0,0 +1,56 @@
1
+ /**
2
+ * smarthr-ui v96 → v97 移行ルール
3
+ *
4
+ * v97での破壊的変更を検出します(自動修正なし)。
5
+ *
6
+ * 対応する破壊的変更:
7
+ * 1. TabItem の onClick 型変更: (tabId: string) => void → (e: MouseEvent) => void
8
+ *
9
+ * 参考: https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v97.0.0
10
+ */
11
+
12
+ const { setupSmarthrUiAliasOptions } = require('../../helpers')
13
+
14
+ // ============================================================
15
+ // 定数定義
16
+ // ============================================================
17
+
18
+ // v97を示す定数(メッセージで使用)
19
+ const TARGET_VERSION = 'v97'
20
+
21
+ // README.mdへのGitHubリンク(エラーメッセージで使用)
22
+ const README_URL =
23
+ 'https://github.com/kufu/tamatebako/blob/master/packages/eslint-plugin-smarthr/rules/autofixer-smarthr-ui-migration/versions/v96-to-v97/README.md'
24
+
25
+ // ============================================================
26
+ // モジュールエクスポート
27
+ // ============================================================
28
+
29
+ module.exports = {
30
+ messages: {
31
+ migrateTabItemOnClick:
32
+ 'smarthr-ui {{to}} では TabItem の onClick の型が変更されました。引数を (tabId: string) から (e: MouseEvent<HTMLButtonElement>) に変更し、tabId の使用箇所を e.currentTarget.value に置き換えてください。注意: このエラーは手動修正後も消えません。対応完了後は { from: "96", to: "97" } 設定を削除してください。詳細: {{readmeUrl}}',
33
+ },
34
+
35
+ createCheckers(context, sourceCode, options = {}) {
36
+ const { validSources, isAliasFile, filename } = setupSmarthrUiAliasOptions(context, options)
37
+
38
+ const checkers = {
39
+ // ============================================================
40
+ // 1. TabItem の onClick 型変更(検出のみ、自動修正なし)
41
+ // TabItemで終わるコンポーネント(CustomTabItem等のラップコンポーネント)も対象
42
+ // ============================================================
43
+
44
+ 'JSXOpeningElement[name.name=/TabItem$/] > JSXAttribute[name.name="onClick"]'(node) {
45
+ context.report({
46
+ node,
47
+ messageId: 'migrateTabItemOnClick',
48
+ data: { to: TARGET_VERSION, readmeUrl: README_URL },
49
+ // fix関数を提供しない = 自動修正不可
50
+ })
51
+ },
52
+ }
53
+
54
+ return checkers
55
+ },
56
+ }