eslint-plugin-smarthr 6.16.0 → 6.17.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
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.17.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.16.0...eslint-plugin-smarthr-v6.17.0) (2026-06-08)
6
+
7
+
8
+ ### Features
9
+
10
+ * add smarthr-ui v94 to v95 migrator ([#1334](https://github.com/kufu/tamatebako/issues/1334)) ([0d2692c](https://github.com/kufu/tamatebako/commit/0d2692cdf272f32f730623b672594c0898155742))
11
+ * best-practice-for-lazy-variable ルールを追加 ([#1335](https://github.com/kufu/tamatebako/issues/1335)) ([a849c1c](https://github.com/kufu/tamatebako/commit/a849c1cb5bf5a7e940ff56b75d11c93ffb79e9da))
12
+
5
13
  ## [6.16.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v6.15.0...eslint-plugin-smarthr-v6.16.0) (2026-05-19)
6
14
 
7
15
 
package/README.md CHANGED
@@ -26,6 +26,7 @@
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)
29
30
  - [best-practice-for-layouts](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts)
30
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)
31
32
  - [best-practice-for-optional-chaining](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-optional-chaining)
@@ -0,0 +1,104 @@
1
+ /**
2
+ * AST操作の汎用ユーティリティ
3
+ */
4
+
5
+ const FUNCTION_SCOPE_TYPES = new Set([
6
+ 'FunctionDeclaration',
7
+ 'FunctionExpression',
8
+ 'ArrowFunctionExpression',
9
+ ])
10
+
11
+ const LOOP_STATEMENT_TYPES = new Set([
12
+ 'ForStatement',
13
+ 'ForInStatement',
14
+ 'ForOfStatement',
15
+ 'WhileStatement',
16
+ 'DoWhileStatement',
17
+ ])
18
+
19
+ /**
20
+ * ノードが関数スコープかどうか判定
21
+ */
22
+ function isFunctionScope(node) {
23
+ return FUNCTION_SCOPE_TYPES.has(node.type)
24
+ }
25
+
26
+ /**
27
+ * ループ構文かどうか判定
28
+ */
29
+ function isLoopStatement(node) {
30
+ return LOOP_STATEMENT_TYPES.has(node.type)
31
+ }
32
+
33
+ /**
34
+ * スコープのstatements配列を取得
35
+ */
36
+ function getStatements(scope) {
37
+ return scope.body || scope.statements || []
38
+ }
39
+
40
+ /**
41
+ * あるノードが別のノードを含んでいるか確認
42
+ */
43
+ function containsNode(parent, target) {
44
+ if (parent === target) return true
45
+
46
+ function traverse(node) {
47
+ if (node === target) return true
48
+ if (!node || typeof node !== 'object') return false
49
+
50
+ for (const key in node) {
51
+ if (key === 'parent') continue
52
+ const child = node[key]
53
+ if (child && (
54
+ (Array.isArray(child) && child.some(c => traverse(c))) ||
55
+ (typeof child === 'object' && traverse(child))
56
+ )) {
57
+ return true
58
+ }
59
+ }
60
+ return false
61
+ }
62
+
63
+ return traverse(parent)
64
+ }
65
+
66
+ /**
67
+ * 指定した型のノードが含まれているかチェック(関数スコープを超えない)
68
+ */
69
+ function containsNodeType(node, nodeType) {
70
+ if (!node || typeof node !== 'object') return false
71
+ if (node.type === nodeType) return true
72
+
73
+ // 関数スコープを超えない
74
+ if (isFunctionScope(node)) return false
75
+
76
+ for (const key in node) {
77
+ if (key === 'parent') continue
78
+ const child = node[key]
79
+ if (child && (
80
+ (Array.isArray(child) && child.some(c => containsNodeType(c, nodeType))) ||
81
+ (typeof child === 'object' && containsNodeType(child, nodeType))
82
+ )) {
83
+ return true
84
+ }
85
+ }
86
+
87
+ return false
88
+ }
89
+
90
+ /**
91
+ * await式が含まれているかチェック
92
+ */
93
+ function containsAwait(node) {
94
+ return containsNodeType(node, 'AwaitExpression')
95
+ }
96
+
97
+ module.exports = {
98
+ isFunctionScope,
99
+ isLoopStatement,
100
+ getStatements,
101
+ containsNode,
102
+ containsNodeType,
103
+ containsAwait,
104
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-smarthr",
3
- "version": "6.16.0",
3
+ "version": "6.17.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/v93-to-v94/REFERENCE.md(実装パターンの詳細説明)
70
- - rules/autofixer-smarthr-ui-migration/versions/v93-to-v94/index.js(実装例)
71
- - rules/autofixer-smarthr-ui-migration/versions/v93-to-v94/README.md(ユーザー向け移行ガイド)
72
- - rules/autofixer-smarthr-ui-migration/versions/v93-to-v94/test.js(テストケース)
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(テストケース)
73
73
  - test/autofixer-smarthr-ui-migration.js(メインテスト)
74
74
  - libs/common.js(rootPathの取得、tsconfig.jsonのpaths設定読み込み)
75
75
 
@@ -588,7 +588,7 @@ https://github.com/kufu/smarthr-ui/releases
588
588
 
589
589
  各versionディレクトリに`REFERENCE.md`があり、実装パターンや注意点が記載されています。
590
590
 
591
- **最新version:** [v93-to-v94/REFERENCE.md](./versions/v93-to-v94/REFERENCE.md)
591
+ **最新version:** [v94-to-v95/REFERENCE.md](./versions/v94-to-v95/REFERENCE.md)
592
592
 
593
593
  このドキュメントには以下が含まれます:
594
594
  - ファイル構造と各セクションの説明
@@ -195,6 +195,7 @@ export const ActionDialog = (props) => <div>{props.children}</div>
195
195
  | `91` → `92` | [移行ガイド](./versions/v91-to-v92/README.md) |
196
196
  | `92` → `93` | [移行ガイド](./versions/v92-to-v93/README.md) |
197
197
  | `93` → `94` | [移行ガイド](./versions/v93-to-v94/README.md) |
198
+ | `94` → `95` | [移行ガイド](./versions/v94-to-v95/README.md) |
198
199
 
199
200
  ## 使用方法
200
201
 
@@ -19,6 +19,7 @@ const v90ToV91 = require('./versions/v90-to-v91/index')
19
19
  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
+ const v94ToV95 = require('./versions/v94-to-v95/index')
22
23
 
23
24
  // サポートしているバージョン間の移行モジュール
24
25
  const VERSION_MODULES = {
@@ -26,6 +27,7 @@ const VERSION_MODULES = {
26
27
  'v91-v92': v91ToV92,
27
28
  'v92-v93': v92ToV93,
28
29
  'v93-v94': v93ToV94,
30
+ 'v94-v95': v94ToV95,
29
31
  }
30
32
 
31
33
  module.exports = {
@@ -60,6 +62,8 @@ module.exports = {
60
62
  ...v90ToV91.messages,
61
63
  ...v91ToV92.messages,
62
64
  ...v92ToV93.messages,
65
+ ...v93ToV94.messages,
66
+ ...v94ToV95.messages,
63
67
  },
64
68
  },
65
69
  create(context) {
@@ -0,0 +1,309 @@
1
+ # smarthr-ui v94 → v95 移行ガイド
2
+
3
+ このドキュメントは、smarthr-ui v94からv95への移行に必要な変更をまとめたものです。
4
+
5
+ ## 対応する破壊的変更
6
+
7
+ ### 1. LanguageSwitcher: decorators属性の削除
8
+
9
+ v95では、`LanguageSwitcher`コンポーネントから`decorators`属性が削除されました。翻訳はsmarthr-ui内で自動的に行われます。
10
+
11
+ #### 変更内容
12
+
13
+ - `decorators` 属性削除
14
+ - トリガーラベルは常に`'Language'`で固定
15
+ - チェックアイコンのaltはsmarthr-uiの翻訳が自動適用(全9言語対応済み)
16
+
17
+ #### 移行方法
18
+
19
+ **Before (v94):**
20
+ ```tsx
21
+ <LanguageSwitcher decorators={{ triggerLabel: () => 'Language' }} />
22
+ ```
23
+
24
+ **After (v95):**
25
+ ```tsx
26
+ <LanguageSwitcher />
27
+ ```
28
+
29
+ #### 自動修正可能なパターン
30
+
31
+ 以下のパターンは、ESLintの`--fix`オプションで自動的に修正されます:
32
+
33
+ ```tsx
34
+ // decorators属性を削除
35
+ <LanguageSwitcher decorators={{ triggerLabel: () => '言語' }} />
36
+ → <LanguageSwitcher />
37
+ ```
38
+
39
+ ### 1-2. AppLauncher: decorators.triggerLabelをtriggerLabel属性に移行
40
+
41
+ v95では、`AppLauncher`コンポーネントから`decorators`属性が削除され、`triggerLabel`属性が追加されました。
42
+
43
+ #### 変更内容
44
+
45
+ - `decorators.triggerLabel` → `triggerLabel` 属性に移行
46
+ - `triggerLabel`が指定されていない場合はsmarthr-uiの翻訳が自動適用(全9言語対応済み)
47
+ - 動的な値(例: featureName)を渡す必要がある場合のみ、`triggerLabel`属性を使用
48
+
49
+ #### 移行方法
50
+
51
+ **Before (v94):**
52
+ ```tsx
53
+ // 固定値の場合
54
+ <AppLauncher decorators={{ triggerLabel: () => 'Apps' }} />
55
+
56
+ // 動的な値の場合
57
+ <AppLauncher decorators={{ triggerLabel: () => featureName }} />
58
+ ```
59
+
60
+ **After (v95):**
61
+ ```tsx
62
+ // 固定値の場合 → decoratorsを削除してIntlProviderに任せる
63
+ <AppLauncher />
64
+
65
+ // 動的な値の場合 → triggerLabel属性に移行
66
+ <AppLauncher triggerLabel={featureName} />
67
+ ```
68
+
69
+ #### 自動修正可能なパターン
70
+
71
+ 以下のパターンは、ESLintの`--fix`オプションで自動的に修正されます:
72
+
73
+ ```tsx
74
+ // 固定値の場合 → decoratorsを削除
75
+ <AppLauncher decorators={{ triggerLabel: () => "Apps" }} />
76
+ → <AppLauncher />
77
+
78
+ <AppLauncher decorators={{ triggerLabel: () => 'アプリ' }} />
79
+ → <AppLauncher />
80
+
81
+ // 動的な値の場合 → triggerLabel属性に移行
82
+ <AppLauncher decorators={{ triggerLabel: () => featureName }} />
83
+ → <AppLauncher triggerLabel={featureName} />
84
+
85
+ <AppLauncher decorators={{ triggerLabel: () => getLabel() }} />
86
+ → <AppLauncher triggerLabel={getLabel()} />
87
+
88
+ <AppLauncher decorators={{ triggerLabel: () => labels.app }} />
89
+ → <AppLauncher triggerLabel={labels.app} />
90
+ ```
91
+
92
+ **注意:** 引数ありの関数(例: `(lang) => ...`)やBlockStatement形式(例: `() => { return "Apps" }`)は自動修正できません。手動で対応してください。
93
+
94
+ ### 2. InputFile: decorators属性の削除
95
+
96
+ v95では、`InputFile`コンポーネントから`decorators`属性が削除されました。削除ボタンのラベルはsmarthr-uiが提供する翻訳が自動的に適用されます(IntlProvider経由)。
97
+
98
+ #### 移行方法
99
+
100
+ **Before (v94):**
101
+ ```tsx
102
+ <InputFile decorators={{ deleteButtonLabel: () => '削除' }} />
103
+ ```
104
+
105
+ **After (v95):**
106
+ ```tsx
107
+ <InputFile />
108
+ ```
109
+
110
+ ### 3. FormDialog: ボタン属性をObject形式に統合
111
+
112
+ v95では、`FormDialog`のボタン関連の属性がObject形式に統合されました。
113
+
114
+ #### 変更内容
115
+
116
+ 以下のpropsが削除されました:
117
+ - `actionText` → `actionButton`で指定
118
+ - `actionTheme` → `actionButton={{ text: "...", theme: "..." }}`で指定
119
+ - `actionDisabled` → `actionButton={{ text: "...", disabled: true }}`で指定
120
+ - `closeDisabled` → `closeButton={{ text: "...", disabled: true }}`で指定
121
+ - `decorators.closeButtonLabel` → `closeButton="キャンセル"`で指定
122
+
123
+ #### 移行方法
124
+
125
+ **シンプルな使い方(文字列のみ指定):**
126
+ ```tsx
127
+ // Before (v94)
128
+ <FormDialog
129
+ actionText="保存"
130
+ decorators={{ closeButtonLabel: () => 'キャンセル' }}
131
+ >
132
+
133
+ // After (v95)
134
+ <FormDialog
135
+ actionButton="保存"
136
+ closeButton="キャンセル"
137
+ >
138
+ ```
139
+
140
+ **詳細な設定が必要な場合:**
141
+ ```tsx
142
+ // Before (v94)
143
+ <FormDialog
144
+ actionText="削除"
145
+ actionTheme="danger"
146
+ actionDisabled={false}
147
+ closeDisabled={true}
148
+ decorators={{ closeButtonLabel: () => '閉じる' }}
149
+ >
150
+
151
+ // After (v95)
152
+ <FormDialog
153
+ actionButton={{ text: "削除", theme: "danger", disabled: false }}
154
+ closeButton={{ text: "閉じる", disabled: true }}
155
+ >
156
+ ```
157
+
158
+ #### 自動修正可能なパターン
159
+
160
+ 以下のパターンは、ESLintの`--fix`オプションで自動的に修正されます:
161
+
162
+ ```tsx
163
+ // actionText のみの場合は自動でリネーム
164
+ <FormDialog actionText="保存">
165
+ → <FormDialog actionButton="保存">
166
+
167
+ // 複数の属性がある場合は自動でObject形式に変換
168
+ <FormDialog actionText="削除" actionTheme="danger">
169
+ → <FormDialog actionButton={{ text: "削除", theme: "danger" }}>
170
+
171
+ <FormDialog actionText="保存" actionDisabled={true}>
172
+ → <FormDialog actionButton={{ text: "保存", disabled: true }}>
173
+
174
+ // decorators.closeButtonLabel(引数なしの関数の場合)
175
+ <FormDialog decorators={{ closeButtonLabel: () => "キャンセル" }}>
176
+ → <FormDialog closeButton="キャンセル">
177
+
178
+ <FormDialog decorators={{ closeButtonLabel: () => buttonLabel }}>
179
+ → <FormDialog closeButton={buttonLabel}>
180
+
181
+ <FormDialog decorators={{ closeButtonLabel: () => getLabel() }}>
182
+ → <FormDialog closeButton={getLabel()}>
183
+
184
+ <FormDialog decorators={{ closeButtonLabel: () => labels.close }}>
185
+ → <FormDialog closeButton={labels.close}>
186
+ ```
187
+
188
+ **注意:** 引数ありの関数(例: `(lang) => ...`)やBlockStatement形式(例: `() => { return "OK" }`)は自動修正できません。手動で対応してください。
189
+
190
+ ### 4. ActionDialog: ボタン属性をObject形式に統合
191
+
192
+ `ActionDialog`も`FormDialog`と同様に、ボタン関連の属性がObject形式に統合されました。
193
+
194
+ #### 変更内容と移行方法
195
+
196
+ FormDialogと同じです。詳細は「3. FormDialog」セクションを参照してください。
197
+
198
+ ### 5. MessageDialog: decorators削除とcloseButton属性への統一
199
+
200
+ v95では、`MessageDialog`の`decorators.closeButtonLabel`が`closeButton`属性に統一されました。
201
+
202
+ #### 変更内容
203
+
204
+ 以下のpropsが削除されました:
205
+ - `decorators.closeButtonLabel` → `closeButton`で指定
206
+
207
+ #### 移行方法
208
+
209
+ **デフォルトラベル使用の場合(省略可能):**
210
+ ```tsx
211
+ // Before (v94)
212
+ <MessageDialog heading="確認">
213
+ メッセージ本文
214
+ </MessageDialog>
215
+
216
+ // After (v95) - 変更なし
217
+ <MessageDialog heading="確認">
218
+ メッセージ本文
219
+ </MessageDialog>
220
+ ```
221
+
222
+ **カスタムラベルが必要な場合:**
223
+ ```tsx
224
+ // Before (v94)
225
+ <MessageDialog
226
+ heading="確認"
227
+ decorators={{ closeButtonLabel: () => 'OK' }}
228
+ >
229
+ メッセージ本文
230
+ </MessageDialog>
231
+
232
+ // After (v95)
233
+ <MessageDialog heading="確認" closeButton="OK">
234
+ メッセージ本文
235
+ </MessageDialog>
236
+ ```
237
+
238
+ #### 自動修正可能なパターン
239
+
240
+ 以下のパターンは、ESLintの`--fix`オプションで自動的に修正されます:
241
+
242
+ ```tsx
243
+ // 引数なしの関数から値を抽出
244
+ <MessageDialog decorators={{ closeButtonLabel: () => "OK" }} />
245
+ → <MessageDialog closeButton="OK" />
246
+
247
+ <MessageDialog decorators={{ closeButtonLabel: () => buttonLabel }} />
248
+ → <MessageDialog closeButton={buttonLabel} />
249
+
250
+ <MessageDialog decorators={{ closeButtonLabel: () => getLabel() }} />
251
+ → <MessageDialog closeButton={getLabel()} />
252
+
253
+ <MessageDialog decorators={{ closeButtonLabel: () => labels.close }} />
254
+ → <MessageDialog closeButton={labels.close} />
255
+ ```
256
+
257
+ **注意:** 引数ありの関数(例: `(lang) => ...`)やBlockStatement形式(例: `() => { return "OK" }`)は自動修正できません。手動で対応してください。
258
+
259
+ ## ESLintルールの使用方法
260
+
261
+ ### .eslintrc.js の設定
262
+
263
+ ```javascript
264
+ module.exports = {
265
+ rules: {
266
+ 'smarthr/autofixer-smarthr-ui-migration': ['error', { from: '94', to: '95' }],
267
+ },
268
+ }
269
+ ```
270
+
271
+ ### 自動修正の実行
272
+
273
+ ```bash
274
+ # エラーを確認
275
+ pnpm run lint
276
+
277
+ # 自動修正を実行
278
+ pnpm run lint --fix
279
+ ```
280
+
281
+ ### 注意事項
282
+
283
+ - 以下のパターンは自動修正できません。エラーメッセージを確認して、手動で修正してください:
284
+ - `closeDisabled`属性の移行(`closeButton`のObject形式への変換が必要)
285
+ - 引数ありの関数: `decorators={{ closeButtonLabel: (lang) => ... }}`、`decorators={{ triggerLabel: (lang) => ... }}`
286
+ - BlockStatement形式の関数: `decorators={{ closeButtonLabel: () => { return "OK" } }}`、`decorators={{ triggerLabel: () => { return "Apps" } }}`
287
+
288
+ ### smarthrUiAlias オプション
289
+
290
+ プロジェクト固有のsmarthr-ui aliasパスを使用している場合は、`smarthrUiAlias`オプションを指定してください。
291
+
292
+ ```javascript
293
+ module.exports = {
294
+ rules: {
295
+ 'smarthr/autofixer-smarthr-ui-migration': [
296
+ 'error',
297
+ {
298
+ from: '94',
299
+ to: '95',
300
+ smarthrUiAlias: '@/components/parts/smarthr-ui', // プロジェクト固有のalias
301
+ },
302
+ ],
303
+ },
304
+ }
305
+ ```
306
+
307
+ ## 参考リンク
308
+
309
+ - [smarthr-ui v95.0.0 リリースノート](https://github.com/kufu/smarthr-ui/releases/tag/smarthr-ui-v95.0.0)