eslint-plugin-smarthr 2.3.0 → 2.5.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 +20 -0
- package/package.json +2 -2
- package/rules/a11y-anchor-has-href-attribute/index.js +1 -0
- package/rules/a11y-clickable-element-has-text/index.js +1 -0
- package/rules/a11y-delegate-element-has-role-presentation/index.js +2 -0
- package/rules/a11y-form-control-in-form/index.js +1 -0
- package/rules/a11y-heading-in-sectioning-content/README.md +16 -1
- package/rules/a11y-heading-in-sectioning-content/index.js +7 -2
- package/rules/a11y-help-link-with-support-href/index.js +2 -1
- package/rules/a11y-image-has-alt-attribute/index.js +2 -0
- package/rules/a11y-input-has-name-attribute/index.js +6 -3
- package/rules/a11y-input-in-form-control/index.js +11 -4
- package/rules/a11y-numbered-text-within-ol/index.js +5 -0
- package/rules/a11y-prohibit-checkbox-or-radio-in-table-cell/index.js +5 -23
- package/rules/a11y-prohibit-input-maxlength-attribute/index.js +5 -4
- package/rules/a11y-prohibit-input-placeholder/index.js +7 -3
- package/rules/a11y-prohibit-sectioning-content-in-form/index.js +2 -0
- package/rules/a11y-prohibit-useless-sectioning-fragment/index.js +2 -1
- package/rules/a11y-trigger-has-button/index.js +4 -2
- package/rules/best-practice-for-async-current-target/index.js +2 -2
- package/rules/best-practice-for-button-element/index.js +1 -0
- package/rules/best-practice-for-data-test-attribute/index.js +1 -0
- package/rules/best-practice-for-date/index.js +2 -0
- package/rules/best-practice-for-layouts/index.js +22 -10
- package/rules/best-practice-for-nested-attributes-array-index/index.js +1 -0
- package/rules/best-practice-for-remote-trigger-dialog/index.js +2 -1
- package/rules/best-practice-for-tailwind-prohibit-root-margin/index.js +2 -1
- package/rules/best-practice-for-tailwind-variants/index.js +6 -3
- package/rules/component-name/README.md +11 -3
- package/rules/component-name/index.js +135 -2
- package/rules/design-system-guideline-prohibit-double-icons/index.js +1 -0
- package/rules/format-import-path/index.js +2 -1
- package/rules/jsx-start-with-spread-attributes/index.js +2 -1
- package/rules/no-import-other-domain/index.js +2 -1
- package/rules/prohibit-export-array-type/index.js +1 -0
- package/rules/prohibit-file-name/index.js +2 -1
- package/rules/prohibit-import/index.js +4 -2
- package/rules/prohibit-path-within-template-literal/index.js +2 -1
- package/rules/require-barrel-import/index.js +2 -1
- package/rules/require-declaration/index.js +4 -2
- package/rules/require-export/index.js +2 -1
- package/rules/require-i18n-text/index.js +4 -2
- package/rules/require-import/index.js +2 -1
- package/rules/trim-props/index.js +24 -12
- package/test/a11y-anchor-has-href-attribute.js +1 -0
- package/test/a11y-clickable-element-has-text.js +1 -0
- package/test/a11y-delegate-element-has-role-presentation.js +2 -0
- package/test/a11y-form-control-in-form.js +1 -0
- package/test/a11y-heading-in-sectioning-content.js +7 -2
- package/test/a11y-help-link-with-support-href.js +2 -1
- package/test/a11y-image-has-alt-attribute.js +2 -0
- package/test/a11y-input-has-name-attribute.js +30 -15
- package/test/a11y-input-in-form-control.js +15 -1
- package/test/a11y-numbered-text-within-ol.js +29 -0
- package/test/a11y-prohhibit-input-placeholder.js +19 -9
- package/test/a11y-prohibit-checkbox-or-radio-in-table-cell.js +35 -15
- package/test/a11y-prohibit-input-maxlength-attribute.js +5 -4
- package/test/a11y-prohibit-useless-sectioning-fragment.js +2 -1
- package/test/a11y-trigger-has-button.js +12 -6
- package/test/best-practice-for-async-current-target.js +2 -2
- package/test/best-practice-for-button-element.js +2 -0
- package/test/best-practice-for-data-test-attribute.js +1 -0
- package/test/best-practice-for-date.js +2 -0
- package/test/best-practice-for-layouts.js +26 -12
- package/test/best-practice-for-nested-attributes-array-index.js +1 -0
- package/test/best-practice-for-remote-trigger-dialog.js +6 -3
- package/test/best-practice-for-tailwind-prohibit-root-margin.js +2 -2
- package/test/best-practice-for-tailwind-variants.js +8 -4
- package/test/component-name.js +11 -2
- package/test/design-system-guideline-prohibit-double-icons.js +1 -0
- package/test/prohibit-file-name.js +4 -2
- package/test/prohibit-import.js +14 -7
- package/test/prohibit-path-within-template-literal.js +4 -2
- package/test/require-declaration.js +11 -5
- package/test/require-export.js +6 -3
- package/test/require-i18n-text.js +4 -3
- package/test/require-import.js +13 -7
- package/test/trim-props.js +23 -14
- package/libs/format_styled_components.js +0 -126
|
@@ -92,6 +92,7 @@ module.exports = {
|
|
|
92
92
|
context.report({
|
|
93
93
|
node,
|
|
94
94
|
message: `${nodeName} に "gap={0}" が指定されており、smarthr-ui/${layoutType} の利用方法として誤っている可能性があります。以下の修正方法を検討してください。
|
|
95
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts
|
|
95
96
|
- 方法1: 子要素を一つにまとめられないか検討してください
|
|
96
97
|
- 例: "<Stack gap={0}><p>hoge</p><p>fuga</p></Stack>" を "<p>hoge<br />fuga</p>" にするなど
|
|
97
98
|
- 方法2: 子要素のstyleを確認しgap属性を0以外にできないか検討してください
|
|
@@ -115,8 +116,10 @@ module.exports = {
|
|
|
115
116
|
node,
|
|
116
117
|
message:
|
|
117
118
|
(justifyAttr?.value.value === 'center' || alignAttr?.value.value === 'center')
|
|
118
|
-
? `${nodeName} は smarthr-ui/${layoutType} ではなく smarthr-ui/Center
|
|
119
|
+
? `${nodeName} は smarthr-ui/${layoutType} ではなく smarthr-ui/Center でマークアップしてください
|
|
120
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`
|
|
119
121
|
: `${nodeName}には子要素が一つしか無いため、${layoutType}でマークアップする意味がありません。
|
|
122
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts
|
|
120
123
|
- styleを確認し、div・spanなど、別要素でマークアップし直すか、${nodeName}を削除してください
|
|
121
124
|
- as, forwardedAsなどでSectioningContent系要素に変更している場合、対応するsmarthr-ui/Section, Aside, Nav, Article のいずれかに差し替えてください`
|
|
122
125
|
})
|
|
@@ -128,55 +131,64 @@ module.exports = {
|
|
|
128
131
|
|
|
129
132
|
context.report({
|
|
130
133
|
node,
|
|
131
|
-
message: `Headingの子孫に${component}を置くことはできません。Headingの外で${component}
|
|
134
|
+
message: `Headingの子孫に${component}を置くことはできません。Headingの外で${component}を使用するようにマークアップを修正してください。
|
|
135
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`
|
|
132
136
|
})
|
|
133
137
|
},
|
|
134
138
|
[`${HEADING_ELEMENT} ${STACK_ELEMENT_NOT_SPAN}`]: (node) => {
|
|
135
139
|
context.report({
|
|
136
140
|
node,
|
|
137
|
-
message:
|
|
141
|
+
message: `Headingの子孫にStackを置く場合、as属性、もしくはforwardedAs属性に \`span\` を指定してください
|
|
142
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
138
143
|
})
|
|
139
144
|
},
|
|
140
145
|
[`${HEADING_ELEMENT} :matches(${ICON_ELEMENT_WITH_TEXT},${TEXT_ELEMENT_WITH_PREFIX})`]: (node) => {
|
|
141
146
|
context.report({
|
|
142
147
|
node,
|
|
143
|
-
message:
|
|
148
|
+
message: `HeadingにIconを設定する場合 <Heading icon={<XxxIcon />}></Heading> のようにicon属性を利用してください
|
|
149
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
144
150
|
})
|
|
145
151
|
},
|
|
146
152
|
[`${FORM_CONTROL_LABEL_ATTRIBUTE} ${INVALID_ELEMENT}`]: (node) => {
|
|
147
153
|
context.report({
|
|
148
154
|
node,
|
|
149
|
-
message: `FormControlのlabel属性に${node.name.name.match(TARGET_INVALID_COMPONENT_REGEX)[1]}を置くことはできません。ラベル用テキスト以外をstatusLabels、subActionArea、もしくはlabel属性のObjectとして '{ text: テキスト, icon: <XxxIcon /> }'
|
|
155
|
+
message: `FormControlのlabel属性に${node.name.name.match(TARGET_INVALID_COMPONENT_REGEX)[1]}を置くことはできません。ラベル用テキスト以外をstatusLabels、subActionArea、もしくはlabel属性のObjectとして '{ text: テキスト, icon: <XxxIcon /> }'に置き換えてください。
|
|
156
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
150
157
|
})
|
|
151
158
|
},
|
|
152
159
|
[`${FORM_CONTROL_LABEL_ATTRIBUTE} ${STACK_ELEMENT_NOT_SPAN}`]: (node) => {
|
|
153
160
|
context.report({
|
|
154
161
|
node,
|
|
155
|
-
message:
|
|
162
|
+
message: `FormControlのlabel属性にStackを置く場合、as属性、もしくはforwardedAs属性に \`span\` を指定してください
|
|
163
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
156
164
|
})
|
|
157
165
|
},
|
|
158
166
|
[`${FORM_CONTROL_LABEL_ATTRIBUTE} :matches(${ICON_ELEMENT_WITH_TEXT},${TEXT_ELEMENT_WITH_PREFIX})`]: (node) => {
|
|
159
167
|
context.report({
|
|
160
168
|
node,
|
|
161
|
-
message:
|
|
169
|
+
message: `FormControlのlabel属性にアイコンを設定する場合 <FormControl label={{ text: 'テキスト', icon: <XxxIcon /> }} /> のようにlabel.icon属性を利用してください
|
|
170
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
162
171
|
})
|
|
163
172
|
},
|
|
164
173
|
[`${FIELDSET_LEGEND_ATTRIBUTE} ${INVALID_ELEMENT}`]: (node) => {
|
|
165
174
|
context.report({
|
|
166
175
|
node,
|
|
167
|
-
message: `Fieldsetのlegend属性に${node.name.name.match(TARGET_INVALID_COMPONENT_REGEX)[1]}を置くことはできません。ラベル用テキスト以外をstatusLabels、subActionArea、もしくはlabel属性のObjectとして '{ text: テキスト, icon: <XxxIcon /> }'
|
|
176
|
+
message: `Fieldsetのlegend属性に${node.name.name.match(TARGET_INVALID_COMPONENT_REGEX)[1]}を置くことはできません。ラベル用テキスト以外をstatusLabels、subActionArea、もしくはlabel属性のObjectとして '{ text: テキスト, icon: <XxxIcon /> }'に置き換えてください。
|
|
177
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
168
178
|
})
|
|
169
179
|
},
|
|
170
180
|
[`${FIELDSET_LEGEND_ATTRIBUTE} ${STACK_ELEMENT_NOT_SPAN}`]: (node) => {
|
|
171
181
|
context.report({
|
|
172
182
|
node,
|
|
173
|
-
message:
|
|
183
|
+
message: `Fieldsetのlegend属性にStackを置く場合、as属性、もしくはforwardedAs属性に \`span\` を指定してください
|
|
184
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
174
185
|
})
|
|
175
186
|
},
|
|
176
187
|
[`${FIELDSET_LEGEND_ATTRIBUTE} :matches(${ICON_ELEMENT_WITH_TEXT},${TEXT_ELEMENT_WITH_PREFIX})`]: (node) => {
|
|
177
188
|
context.report({
|
|
178
189
|
node,
|
|
179
|
-
message:
|
|
190
|
+
message: `Fieldsetのlegend属性にアイコンを設定する場合 <Fieldset legend={{ text: 'テキスト', icon: <XxxIcon /> }} /> のようにlegend.icon属性を利用してください
|
|
191
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-layouts`,
|
|
180
192
|
})
|
|
181
193
|
},
|
|
182
194
|
}
|
|
@@ -13,6 +13,7 @@ module.exports = {
|
|
|
13
13
|
context.report({
|
|
14
14
|
node,
|
|
15
15
|
message: `入力要素のname属性に対して、配列に当たる部分の連番を指定しない場合(例: a[xxx][][yyy] )、配列内アイテムの属性が意図せず入れ替わってしまう場合がありえるため、常にindexを設定してください。
|
|
16
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-nested-attributes-array-index
|
|
16
17
|
- 例のyyyに当たる値が配列内の別アイテムに紐づいてしまう場合があります。
|
|
17
18
|
- 詳しくは https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-nested-attributes-array-index を参照してください`,
|
|
18
19
|
})
|
|
@@ -11,7 +11,8 @@ module.exports = {
|
|
|
11
11
|
context.report({
|
|
12
12
|
node,
|
|
13
13
|
message: `${node.parent.name.name}の${node.name.name}属性には直接文字列を指定してください。
|
|
14
|
-
|
|
14
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-remote-trigger-dialog
|
|
15
|
+
- 変数などは利用できません(これは関連するTriggerとDialogを検索しやすくするためです)`,
|
|
15
16
|
})
|
|
16
17
|
}
|
|
17
18
|
|
|
@@ -13,7 +13,8 @@ module.exports = {
|
|
|
13
13
|
':matches(ArrowFunctionExpression,FunctionDeclaration,ReturnStatement)>JSXElement>JSXOpeningElement JSXAttribute[name.name="className"][value.value=/( |^)shr-m[trbl]?-/]': (node) => {
|
|
14
14
|
context.report({
|
|
15
15
|
node,
|
|
16
|
-
message:
|
|
16
|
+
message: `コンポーネントのルート要素に外側への余白(margin)を設定しないでください。外側の余白は使用する側で制御するべきです。
|
|
17
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-tailwind-prohibit-root-margin`,
|
|
17
18
|
})
|
|
18
19
|
},
|
|
19
20
|
}
|
|
@@ -43,7 +43,8 @@ module.exports = {
|
|
|
43
43
|
if (node.source.value === TV_COMPONENTS && node.specifiers.some(findValidImportNameNode)) {
|
|
44
44
|
context.report({
|
|
45
45
|
node,
|
|
46
|
-
message: `${TV_COMPONENTS} をimportする際は、名称が"${TV_COMPONENTS_METHOD}" となるようにしてください。例: "import { ${TV_COMPONENTS_METHOD} } from '${TV_COMPONENTS}'"
|
|
46
|
+
message: `${TV_COMPONENTS} をimportする際は、名称が"${TV_COMPONENTS_METHOD}" となるようにしてください。例: "import { ${TV_COMPONENTS_METHOD} } from '${TV_COMPONENTS}'"
|
|
47
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-tailwind-variants`,
|
|
47
48
|
});
|
|
48
49
|
}
|
|
49
50
|
},
|
|
@@ -54,13 +55,15 @@ module.exports = {
|
|
|
54
55
|
if (idNode && !TV_RESULT_CONST_NAME_REGEX.test(idNode.id.name)) {
|
|
55
56
|
context.report({
|
|
56
57
|
node: idNode,
|
|
57
|
-
message: `${TV_COMPONENTS_METHOD}の実行結果を格納する変数名は "${idNode.id.name}" ではなく "${TV_RESULT_CONST_NAME_REGEX}"にmatch
|
|
58
|
+
message: `${TV_COMPONENTS_METHOD}の実行結果を格納する変数名は "${idNode.id.name}" ではなく "${TV_RESULT_CONST_NAME_REGEX}"にmatchする名称に統一してください。
|
|
59
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-tailwind-variants`,
|
|
58
60
|
});
|
|
59
61
|
}
|
|
60
62
|
} else if (TV_RESULT_CONST_NAME_REGEX.test(node.callee.name) && !findNodeUseMemo(node.parent)) {
|
|
61
63
|
context.report({
|
|
62
64
|
node,
|
|
63
|
-
message: `"${node.callee.name}" を実行する際、useMemo
|
|
65
|
+
message: `"${node.callee.name}" を実行する際、useMemoでラップし、メモ化してください
|
|
66
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-tailwind-variants`,
|
|
64
67
|
});
|
|
65
68
|
}
|
|
66
69
|
},
|
|
@@ -20,13 +20,18 @@
|
|
|
20
20
|
// import 時のasをチェック
|
|
21
21
|
import { HogeSelect as Fuga } from 'any'
|
|
22
22
|
|
|
23
|
-
//
|
|
23
|
+
// 特定の要素と勘違いしてしまうような名称はNG
|
|
24
|
+
// 例: select要素ではないにも関わらずselectを予想してしまう名称を設定している
|
|
24
25
|
const HogeSelect = styled.div
|
|
25
26
|
const HogeSelect = styled(Hoge)
|
|
26
27
|
|
|
27
|
-
//
|
|
28
|
+
// 拡張前の要素がわからないような名称はNG
|
|
29
|
+
// 例: select要素であることがHogeから想像できない
|
|
28
30
|
const Hoge = styled.select
|
|
29
31
|
const Hoge = styled(FugaSelect)
|
|
32
|
+
|
|
33
|
+
// Modalでは意味が通らないパターンがあるためDialogに統一する方針のためNG
|
|
34
|
+
const HogeModal = styled(Any)
|
|
30
35
|
```
|
|
31
36
|
|
|
32
37
|
## ✅ Correct
|
|
@@ -38,7 +43,10 @@ import { HogeSelect as FugaSelect } from 'any'
|
|
|
38
43
|
import { type HogeSelect as Fuga } from 'any'
|
|
39
44
|
import type { HogeSelect as Fuga } from 'any'
|
|
40
45
|
|
|
41
|
-
//
|
|
46
|
+
// あたらしい名称が継承元の要素を予想できるためOK
|
|
42
47
|
const HogeSelect = styled.select
|
|
43
48
|
const HogeSelect = styled(FugaSelect)
|
|
49
|
+
|
|
50
|
+
// ModalではなくDialogが利用されているためOK
|
|
51
|
+
const HogeDialog = styled(Any)
|
|
44
52
|
```
|
|
@@ -1,4 +1,61 @@
|
|
|
1
|
-
const
|
|
1
|
+
const STYLED_COMPONENTS_METHOD = 'styled'
|
|
2
|
+
const STYLED_COMPONENTS = `${STYLED_COMPONENTS_METHOD}-components`
|
|
3
|
+
|
|
4
|
+
const findInvalidImportNameNode = (s) => s.type === 'ImportDefaultSpecifier' && s.local.name !== STYLED_COMPONENTS_METHOD
|
|
5
|
+
|
|
6
|
+
const checkImportStyledComponents = (node, context) => {
|
|
7
|
+
if (node.source.value !== STYLED_COMPONENTS) {
|
|
8
|
+
return
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const invalidNameNode = node.specifiers.find(findInvalidImportNameNode)
|
|
12
|
+
|
|
13
|
+
if (invalidNameNode) {
|
|
14
|
+
context.report({
|
|
15
|
+
node: invalidNameNode,
|
|
16
|
+
message: `${STYLED_COMPONENTS} をimportする際は、名称が"${STYLED_COMPONENTS_METHOD}" となるようにしてください。例: "import ${STYLED_COMPONENTS_METHOD} from '${STYLED_COMPONENTS}'"
|
|
17
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/component-name`,
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const getStyledComponentBaseName = (node) => {
|
|
23
|
+
let base = null
|
|
24
|
+
|
|
25
|
+
if (!node.init) {
|
|
26
|
+
return base
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const tag = node.init.tag || node.init
|
|
30
|
+
|
|
31
|
+
if (tag.object?.name === STYLED_COMPONENTS_METHOD) {
|
|
32
|
+
base = tag.property.name
|
|
33
|
+
} else if (tag.callee) {
|
|
34
|
+
const callee = tag.callee
|
|
35
|
+
|
|
36
|
+
switch (STYLED_COMPONENTS_METHOD) {
|
|
37
|
+
case callee.name: {
|
|
38
|
+
const arg = tag.arguments[0]
|
|
39
|
+
base = arg.name || arg.value
|
|
40
|
+
break
|
|
41
|
+
}
|
|
42
|
+
case callee.callee?.name: {
|
|
43
|
+
const arg = callee.arguments[0]
|
|
44
|
+
base = arg.name || arg.value
|
|
45
|
+
break
|
|
46
|
+
}
|
|
47
|
+
case callee.object?.name:
|
|
48
|
+
base = callee.property.name
|
|
49
|
+
break
|
|
50
|
+
case callee.object?.callee?.name:
|
|
51
|
+
const arg = callee.object.arguments[0]
|
|
52
|
+
base = arg.name || arg.value
|
|
53
|
+
break
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
return base
|
|
58
|
+
}
|
|
2
59
|
|
|
3
60
|
const EXPECTED_NAMES = {
|
|
4
61
|
'(A|^a)rticle$': 'Article$',
|
|
@@ -71,6 +128,7 @@ const EXPECTED_NAMES = {
|
|
|
71
128
|
}
|
|
72
129
|
|
|
73
130
|
const unexpectedMessageTemplate = `{{extended}} は smarthr-ui/{{expected}} をextendすることを期待する名称になっています
|
|
131
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/component-name
|
|
74
132
|
- childrenにHeadingを含まない場合、コンポーネントの名称から"{{expected}}"を取り除いてください
|
|
75
133
|
- childrenにHeadingを含み、アウトラインの範囲を指定するためのコンポーネントならば、smarthr-ui/{{expected}}をexendしてください
|
|
76
134
|
- "styled(Xxxx)" 形式の場合、拡張元であるXxxxコンポーネントの名称の末尾に"{{expected}}"を設定し、そのコンポーネント内でsmarthr-ui/{{expected}}を利用してください`
|
|
@@ -134,7 +192,82 @@ module.exports = {
|
|
|
134
192
|
schema: SCHEMA,
|
|
135
193
|
},
|
|
136
194
|
create(context) {
|
|
137
|
-
|
|
195
|
+
const entriesesTagNames = Object.entries(EXPECTED_NAMES).map(([b, e]) => [ new RegExp(b), new RegExp(e) ])
|
|
196
|
+
const entriesesUnTagNames = UNEXPECTED_NAMES ? Object.entries(UNEXPECTED_NAMES).map(([b, e]) => {
|
|
197
|
+
const [ auctualE, messageTemplate ] = Array.isArray(e) ? e : [e, '']
|
|
198
|
+
|
|
199
|
+
return [ new RegExp(b), new RegExp(auctualE), messageTemplate ]
|
|
200
|
+
}) : []
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
const checkImportedNameToLocalName = (node, base, extended, isImport) => {
|
|
204
|
+
entriesesTagNames.forEach(([b, e]) => {
|
|
205
|
+
if (base.match(b) && !extended.match(e)) {
|
|
206
|
+
context.report({
|
|
207
|
+
node,
|
|
208
|
+
message: `${extended}を正規表現 "${e.toString()}" がmatchする名称に変更してください。
|
|
209
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/component-name${isImport ? `
|
|
210
|
+
- ${base}が型の場合、'import type { ${base} as ${extended} }' もしくは 'import { type ${base} as ${extended} }' のように明示的に型であることを宣言してください。名称変更が不要になります` : ''}`,
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
return {
|
|
217
|
+
ImportDeclaration: (node) => {
|
|
218
|
+
checkImportStyledComponents(node, context)
|
|
219
|
+
|
|
220
|
+
if (node.importKind !== 'type') {
|
|
221
|
+
node.specifiers.forEach((s) => {
|
|
222
|
+
if (s.importKind !== 'type' && s.imported && s.imported.name !== s.local.name) {
|
|
223
|
+
checkImportedNameToLocalName(node, s.imported.name, s.local.name, true)
|
|
224
|
+
}
|
|
225
|
+
})
|
|
226
|
+
}
|
|
227
|
+
},
|
|
228
|
+
VariableDeclarator: (node) => {
|
|
229
|
+
const base = getStyledComponentBaseName(node)
|
|
230
|
+
|
|
231
|
+
if (base) {
|
|
232
|
+
const extended = node.id.name
|
|
233
|
+
|
|
234
|
+
checkImportedNameToLocalName(node, base, extended)
|
|
235
|
+
|
|
236
|
+
entriesesUnTagNames.forEach(([b, e, m]) => {
|
|
237
|
+
const matcher = extended.match(e)
|
|
238
|
+
|
|
239
|
+
if (matcher && !base.match(b)) {
|
|
240
|
+
const expected = matcher[1]
|
|
241
|
+
const isBareTag = base === base.toLowerCase()
|
|
242
|
+
const sampleFixBase = `styled${isBareTag ? `.${base}` : `(${base})`}`
|
|
243
|
+
|
|
244
|
+
context.report({
|
|
245
|
+
node,
|
|
246
|
+
message: m ? m
|
|
247
|
+
.replaceAll('{{extended}}', extended)
|
|
248
|
+
.replaceAll('{{expected}}', expected) : `${extended} は ${b.toString()} にmatchする名前のコンポーネントを拡張することを期待している名称になっています
|
|
249
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/component-name
|
|
250
|
+
- ${extended} の名称の末尾が"${expected}" という文字列ではない状態にしつつ、"${base}"を継承していることをわかる名称に変更してください
|
|
251
|
+
- もしくは"${base}"を"${extended}"の継承元であることがわかるような${isBareTag ? '適切なタグや別コンポーネントに差し替えてください' : '名称に変更するか、適切な別コンポーネントに差し替えてください'}
|
|
252
|
+
- 修正例1: const ${extended.replace(expected, '')}Xxxx = ${sampleFixBase}
|
|
253
|
+
- 修正例2: const ${extended}Xxxx = ${sampleFixBase}
|
|
254
|
+
- 修正例3: const ${extended} = styled(Xxxx${expected})`
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
},
|
|
260
|
+
'VariableDeclarator[id.name=/Modal/]': (node) => {
|
|
261
|
+
context.report({
|
|
262
|
+
node,
|
|
263
|
+
message: `コンポーネント名や変数名に"Modal"という名称は使わず、"Dialog"に統一してください
|
|
264
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/component-name
|
|
265
|
+
- Modalとは形容詞であり、かつ"現在の操作から切り離して専用の操作を行わせる" という意味合いを持ちます
|
|
266
|
+
- そのためDialogでなければ正しくない場合がありえます(smarthr-ui/ModelessDialogのように元々の操作も行えるDialogなどが該当)
|
|
267
|
+
- DialogはModalなダイアログ、Modelessなダイアログすべてを含有した名称のため、統一することを推奨しています`
|
|
268
|
+
})
|
|
269
|
+
},
|
|
270
|
+
}
|
|
138
271
|
},
|
|
139
272
|
}
|
|
140
273
|
module.exports.schema = SCHEMA
|
|
@@ -14,6 +14,7 @@ module.exports = {
|
|
|
14
14
|
context.report({
|
|
15
15
|
node,
|
|
16
16
|
message: `${node.name.name} には prefix と suffix は同時に設定できません。
|
|
17
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/design-system-guideline-prohibit-double-icons
|
|
17
18
|
- どちらにもアイコンをつけられそうな場合は、prefixを優先してください。`,
|
|
18
19
|
})
|
|
19
20
|
}
|
|
@@ -130,7 +130,8 @@ module.exports = {
|
|
|
130
130
|
if (importPath !== fixedImportPath) {
|
|
131
131
|
context.report({
|
|
132
132
|
node,
|
|
133
|
-
message: `${fixedImportPath}
|
|
133
|
+
message: `${fixedImportPath} に修正してください
|
|
134
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/format-import-path`,
|
|
134
135
|
fix: (fixer) => fixer.replaceText(
|
|
135
136
|
node,
|
|
136
137
|
context.sourceCode.getText(node).replace(new RegExp(`from '${importPath}'$`), `from '${fixedImportPath}'`)
|
|
@@ -39,7 +39,8 @@ module.exports = {
|
|
|
39
39
|
|
|
40
40
|
context.report({
|
|
41
41
|
node,
|
|
42
|
-
message: `"${attributeCode}" は意図しない上書きを防ぐため、spread attributes
|
|
42
|
+
message: `"${attributeCode}" は意図しない上書きを防ぐため、spread attributesでない属性より先に記述してください
|
|
43
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/jsx-start-with-spread-attributes`,
|
|
43
44
|
fix: option?.fix ? (fixer) => {
|
|
44
45
|
const elementNode = node.parent
|
|
45
46
|
const sortedAttributes = [...elementNode.attributes].reduce((p, a, i) => {
|
|
@@ -122,7 +122,8 @@ module.exports = {
|
|
|
122
122
|
|
|
123
123
|
context.report({
|
|
124
124
|
node,
|
|
125
|
-
message: `別ドメインから ${importPath}${deniedModules.length ? ` の ${deniedModules.join(', ')}` : ''} がimport
|
|
125
|
+
message: `別ドメインから ${importPath}${deniedModules.length ? ` の ${deniedModules.join(', ')}` : ''} がimportされています。
|
|
126
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/no-import-other-domain`,
|
|
126
127
|
})
|
|
127
128
|
}
|
|
128
129
|
},
|
|
@@ -12,6 +12,7 @@ module.exports = {
|
|
|
12
12
|
context.report({
|
|
13
13
|
node,
|
|
14
14
|
message: `型をexportする際、配列ではなくアイテムの型をexportしてください。
|
|
15
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/prohibit-export-array-type
|
|
15
16
|
- 型を配列でexportすると、その型が配列かどうかを判定するための情報は名称のみになります
|
|
16
17
|
- 名称から配列かどうかを判定しにくい場合があるため、利用するファイル内で配列として型を設定してください`,
|
|
17
18
|
})
|
|
@@ -34,7 +34,8 @@ module.exports = {
|
|
|
34
34
|
matcher = context.filename.match(new RegExp(path))
|
|
35
35
|
|
|
36
36
|
if (matcher) {
|
|
37
|
-
messages.push([...matcher].reduce(((prev, k, index) => prev.replaceAll(`\$${index}`, k)), message
|
|
37
|
+
messages.push([...matcher].reduce(((prev, k, index) => prev.replaceAll(`\$${index}`, k)), `${message}
|
|
38
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/prohibit-file-name`))
|
|
38
39
|
}
|
|
39
40
|
})
|
|
40
41
|
|
|
@@ -33,7 +33,8 @@ const SCHEMA = [{
|
|
|
33
33
|
|
|
34
34
|
const CWD = process.cwd()
|
|
35
35
|
|
|
36
|
-
const defaultReportMessage = (moduleName, exportName) => `${moduleName}${typeof exportName == 'string' ? `/${exportName}`: ''}
|
|
36
|
+
const defaultReportMessage = (moduleName, exportName) => `${moduleName}${typeof exportName == 'string' ? `/${exportName}`: ''} は利用しないでください
|
|
37
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/prohibit-import`
|
|
37
38
|
|
|
38
39
|
/**
|
|
39
40
|
* @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
|
|
@@ -84,7 +85,8 @@ module.exports = {
|
|
|
84
85
|
if (useImported) {
|
|
85
86
|
context.report({
|
|
86
87
|
node,
|
|
87
|
-
message: reportMessage ? reportMessage.replaceAll('{{module}}', node.source.value).replaceAll('{{export}}', useImported)
|
|
88
|
+
message: reportMessage ? `${reportMessage.replaceAll('{{module}}', node.source.value).replaceAll('{{export}}', useImported)}
|
|
89
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/prohibit-import` : defaultReportMessage(node.source.value, useImported)
|
|
88
90
|
});
|
|
89
91
|
}
|
|
90
92
|
}
|
|
@@ -46,7 +46,8 @@ module.exports = {
|
|
|
46
46
|
if (name) {
|
|
47
47
|
context.report({
|
|
48
48
|
node: exp,
|
|
49
|
-
message: `${name}は \`\` で囲まないでください。queryStringを結合するなどのURL生成は ${name} 内で行います。 (例: ${name}({ query: { hoge: 'abc' } })
|
|
49
|
+
message: `${name}は \`\` で囲まないでください。queryStringを結合するなどのURL生成は ${name} 内で行います。 (例: ${name}({ query: { hoge: 'abc' } })
|
|
50
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/prohibit-path-within-template-literal`,
|
|
50
51
|
});
|
|
51
52
|
}
|
|
52
53
|
})
|
|
@@ -185,7 +185,8 @@ module.exports = {
|
|
|
185
185
|
|
|
186
186
|
context.report({
|
|
187
187
|
node,
|
|
188
|
-
message: deniedModules.length ? `${deniedModules.join(', ')} は ${noExt} からimportしてください` : `${noExt} からimportするか、${barrel} のbarrelファイルを削除して直接import
|
|
188
|
+
message: `${deniedModules.length ? `${deniedModules.join(', ')} は ${noExt} からimportしてください` : `${noExt} からimportするか、${barrel} のbarrelファイルを削除して直接import可能にしてください`}
|
|
189
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-barrel-import`,
|
|
189
190
|
});
|
|
190
191
|
}
|
|
191
192
|
},
|
|
@@ -103,7 +103,8 @@ module.exports = {
|
|
|
103
103
|
if (!hit) {
|
|
104
104
|
context.report({
|
|
105
105
|
node,
|
|
106
|
-
message: localOption.reportMessage || `${localOption.type} ${requireDeclaration}
|
|
106
|
+
message: `${localOption.reportMessage || `${localOption.type} ${requireDeclaration}が宣言されていません`}
|
|
107
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-declaration`,
|
|
107
108
|
})
|
|
108
109
|
} else if (localOption.use) {
|
|
109
110
|
const code = context.sourceCode.getText(hit)
|
|
@@ -113,7 +114,8 @@ module.exports = {
|
|
|
113
114
|
if (!useRegex(u).test(code) && (!localOption.reportMessage || !reported)) {
|
|
114
115
|
context.report({
|
|
115
116
|
node: hit,
|
|
116
|
-
message: localOption.reportMessage || `${localOption.type} ${requireDeclaration} では ${u}
|
|
117
|
+
message: `${localOption.reportMessage || `${localOption.type} ${requireDeclaration} では ${u} を利用してください`}
|
|
118
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-declaration`,
|
|
117
119
|
})
|
|
118
120
|
reported = true
|
|
119
121
|
}
|
|
@@ -79,7 +79,8 @@ module.exports = {
|
|
|
79
79
|
if (notExistsExports.length) {
|
|
80
80
|
context.report({
|
|
81
81
|
node,
|
|
82
|
-
message: `${notExistsExports.join(', ')} をexport
|
|
82
|
+
message: `${notExistsExports.join(', ')} をexportしてください
|
|
83
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-export`,
|
|
83
84
|
})
|
|
84
85
|
}
|
|
85
86
|
})
|
|
@@ -55,7 +55,8 @@ module.exports = {
|
|
|
55
55
|
const reportAttributeError = (node) => {
|
|
56
56
|
context.report({
|
|
57
57
|
node,
|
|
58
|
-
message: `${node.parent.name.name}の${node.name.name}
|
|
58
|
+
message: `${node.parent.name.name}の${node.name.name}属性に文字列リテラルが指定されています。多言語化対応のため、翻訳関数を使用してください
|
|
59
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-i18n-text`,
|
|
59
60
|
})
|
|
60
61
|
}
|
|
61
62
|
|
|
@@ -83,7 +84,8 @@ module.exports = {
|
|
|
83
84
|
handlers['JSXText[value=/\\S/]'] = (node) => {
|
|
84
85
|
context.report({
|
|
85
86
|
node,
|
|
86
|
-
message:
|
|
87
|
+
message: `子要素に文字列リテラルが指定されています。多言語化対応のため、翻訳関数を使用してください
|
|
88
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-i18n-text`,
|
|
87
89
|
})
|
|
88
90
|
}
|
|
89
91
|
|
|
@@ -80,7 +80,8 @@ module.exports = {
|
|
|
80
80
|
const reporter = (item) => {
|
|
81
81
|
context.report({
|
|
82
82
|
node,
|
|
83
|
-
message: reportMessage ? reportMessage.replaceAll('{{module}}', actualTarget).replaceAll('{{export}}', item) : defaultReportMessage(actualTarget, item)
|
|
83
|
+
message: `${reportMessage ? reportMessage.replaceAll('{{module}}', actualTarget).replaceAll('{{export}}', item) : defaultReportMessage(actualTarget, item)}
|
|
84
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/require-import`
|
|
84
85
|
})
|
|
85
86
|
}
|
|
86
87
|
|
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
const SCHEMA = []
|
|
2
2
|
|
|
3
|
+
const searchBubbleUp = (node) => {
|
|
4
|
+
switch (node.type) {
|
|
5
|
+
case 'Program':
|
|
6
|
+
case 'JSXAttribute':
|
|
7
|
+
return null
|
|
8
|
+
case 'TemplateLiteral':
|
|
9
|
+
return node
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
return searchBubbleUp(node.parent)
|
|
13
|
+
}
|
|
14
|
+
|
|
3
15
|
/**
|
|
4
16
|
* @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
|
|
5
17
|
*/
|
|
@@ -10,21 +22,21 @@ module.exports = {
|
|
|
10
22
|
fixable: 'whitespace',
|
|
11
23
|
},
|
|
12
24
|
create(context) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
node,
|
|
17
|
-
message: '属性に設定している文字列から先頭、末尾の空白文字を削除してください',
|
|
18
|
-
fix: (fixer) => fixer.replaceText(node, context.sourceCode.getText(node).replace(/^('|")\s+/, '$1').replace(/\s+('|")$/, '$1')),
|
|
19
|
-
})
|
|
20
|
-
},
|
|
21
|
-
'JSXAttribute TemplateLiteral:has(TemplateElement:matches(:first-child[value.raw=/^ /],:last-child[value.raw=/ $/]))': (node) => {
|
|
25
|
+
const checker = (node) => {
|
|
26
|
+
// HINT: TemplateLiteralがネストしている場合、親側だけチェックする
|
|
27
|
+
if (!searchBubbleUp(node.parent)) {
|
|
22
28
|
return context.report({
|
|
23
29
|
node,
|
|
24
|
-
message:
|
|
25
|
-
|
|
30
|
+
message: `属性に設定している文字列から先頭、末尾の空白文字を削除してください
|
|
31
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/trim-props`,
|
|
32
|
+
fix: (fixer) => fixer.replaceText(node, context.sourceCode.getText(node).replace(/^('|"|`)\s+/, '$1').replace(/\s+('|"|`)$/, '$1')),
|
|
26
33
|
})
|
|
27
|
-
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return {
|
|
38
|
+
'JSXAttribute Literal[value=/(^ | $)/]': checker,
|
|
39
|
+
'JSXAttribute TemplateLiteral:has(>TemplateElement:matches(:first-child[value.raw=/^ /],:last-child[value.raw=/ $/]))': checker,
|
|
28
40
|
}
|
|
29
41
|
},
|
|
30
42
|
}
|
|
@@ -11,6 +11,7 @@ const ruleTester = new RuleTester({
|
|
|
11
11
|
},
|
|
12
12
|
})
|
|
13
13
|
const generateErrorText = (name) => `${name} に href 属性を正しく設定してください
|
|
14
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/a11y-anchor-has-href-attribute
|
|
14
15
|
- onClickなどでページ遷移する場合でもhref属性に遷移先のURIを設定してください
|
|
15
16
|
- Cmd + clickなどのキーボードショートカットに対応出来ます
|
|
16
17
|
- onClickなどの動作がURLの変更を行わない場合、button要素でマークアップすることを検討してください
|
|
@@ -11,6 +11,7 @@ const ruleTester = new RuleTester({
|
|
|
11
11
|
},
|
|
12
12
|
})
|
|
13
13
|
const defaultErrorMessage = `a, buttonなどのクリッカブルな要素内にはテキストを設定してください
|
|
14
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/a11y-clickable-element-has-text
|
|
14
15
|
- 要素内にアイコン、画像のみを設置する場合はaltなどの代替テキスト用属性を指定してください
|
|
15
16
|
- SVG component の場合、altを属性として受け取れるようにした上で '<svg role="img" aria-label={alt}>' のように指定してください
|
|
16
17
|
- クリッカブルな要素内に設置しているコンポーネントがテキストを含んでいる場合、"XxxxText" のように末尾に "Text" もしくは "Message" という名称を設定してください`
|
|
@@ -17,6 +17,7 @@ const messageNonInteractiveEventHandler = (nodeName, onAttrs, interactiveCompone
|
|
|
17
17
|
const onAttrsText = onAttrs.join(', ')
|
|
18
18
|
|
|
19
19
|
return `${nodeName} に${onAttrsText}を設定するとブラウザが正しく解釈が行えず、ユーザーが利用することが出来ない場合があるため、以下のいずれかの対応をおこなってください。
|
|
20
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/a11y-delegate-element-has-role-presentation
|
|
20
21
|
- 方法1: ${nodeName}がinput、buttonやaなどのインタラクティブな要素の場合、コンポーネント名の末尾をインタラクティブなコンポーネントであることがわかる名称に変更してください
|
|
21
22
|
- "${interactiveComponentRegex}" の正規表現にmatchするコンポーネントに差し替える、もしくは名称を変更してください
|
|
22
23
|
- 方法2: ${onAttrsText} がコンポーネント内の特定のインタラクティブな要素に設定される場合、名称を具体的なものに変更してください
|
|
@@ -29,6 +30,7 @@ const messageNonInteractiveEventHandler = (nodeName, onAttrs, interactiveCompone
|
|
|
29
30
|
- 'role="presentation"' を設定する適切な要素が存在しない場合、div、またはspanでイベントが発生する要素を囲んだ上でrole属性を設定してください`
|
|
30
31
|
}
|
|
31
32
|
const messageRolePresentationNotHasInteractive = (nodeName, onAttrs, interactiveComponentRegex = defaultInteractiveRegex) => `${nodeName}に 'role="presentation"' が設定されているにも関わらず、子要素にinput、buttonやaなどのインタラクティブな要素が見つからないため、ブラウザが正しく解釈が行えず、ユーザーが利用することが出来ない場合があるため、以下のいずれかの対応をおこなってください。
|
|
33
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/a11y-delegate-element-has-role-presentation
|
|
32
34
|
- 方法1: 子要素にインタラクティブな要素が存在するにも関わらずこのエラーが表示されている場合、子要素の名称を変更してください
|
|
33
35
|
- "${interactiveComponentRegex}" の正規表現にmatchするよう、インタラクティブな子要素全てを差し替える、もしくは名称を変更してください
|
|
34
36
|
- 方法2: ${nodeName}自体がインタラクティブな要素の場合、'role="presentation"'を削除した上で名称を変更してください
|
|
@@ -11,6 +11,7 @@ const ruleTester = new RuleTester({
|
|
|
11
11
|
},
|
|
12
12
|
})
|
|
13
13
|
const generateErrorText = (elementName) => `${elementName}をform要素で囲むようにマークアップしてください。
|
|
14
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/a11y-form-control-in-form
|
|
14
15
|
- form要素で囲むことでスクリーンリーダーに入力フォームであることが正しく伝わる、入力要素にfocusした状態でEnterを押せばsubmitできる、inputのpattern属性を利用できるなどのメリットがあります
|
|
15
16
|
- 以下のいずれかの方法で修正をおこなってください
|
|
16
17
|
- 方法1: form要素で ${elementName} を囲んでください。smarthr-ui/ActionDialog、もしくはsmarthr-ui/RemoteTriggerActionDialogを利用している場合、smarthr-ui/FormDialog、smarthr-ui/RemoteTriggerFormDialogに置き換えてください
|