eslint-plugin-smarthr 0.5.7 → 0.5.8

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 (39) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +1 -0
  3. package/package.json +3 -2
  4. package/rules/a11y-anchor-has-href-attribute/index.js +3 -0
  5. package/rules/a11y-clickable-element-has-text/index.js +3 -0
  6. package/rules/a11y-delegate-element-has-role-presentation/index.js +3 -0
  7. package/rules/a11y-form-control-in-form/index.js +3 -0
  8. package/rules/a11y-heading-in-sectioning-content/index.js +3 -0
  9. package/rules/a11y-image-has-alt-attribute/index.js +3 -0
  10. package/rules/a11y-input-has-name-attribute/index.js +3 -0
  11. package/rules/a11y-input-in-form-control/index.js +3 -0
  12. package/rules/a11y-numbered-text-within-ol/index.js +3 -0
  13. package/rules/a11y-prohibit-input-maxlength-attribute/README.md +35 -0
  14. package/rules/a11y-prohibit-input-maxlength-attribute/index.js +44 -0
  15. package/rules/a11y-prohibit-input-placeholder/index.js +3 -0
  16. package/rules/a11y-prohibit-useless-sectioning-fragment/index.js +3 -0
  17. package/rules/a11y-replace-unreadable-symbol/index.js +3 -0
  18. package/rules/a11y-trigger-has-button/index.js +3 -0
  19. package/rules/best-practice-for-button-element/index.js +3 -0
  20. package/rules/best-practice-for-date/index.js +3 -0
  21. package/rules/best-practice-for-layouts/index.js +11 -1
  22. package/rules/best-practice-for-remote-trigger-dialog/index.js +3 -0
  23. package/rules/format-import-path/index.js +3 -0
  24. package/rules/format-translate-component/index.js +3 -0
  25. package/rules/jsx-start-with-spread-attributes/index.js +3 -0
  26. package/rules/no-import-other-domain/index.js +3 -0
  27. package/rules/prohibit-export-array-type/index.js +3 -0
  28. package/rules/prohibit-file-name/index.js +3 -0
  29. package/rules/prohibit-import/index.js +3 -0
  30. package/rules/prohibit-path-within-template-literal/index.js +3 -0
  31. package/rules/require-barrel-import/index.js +3 -0
  32. package/rules/require-declaration/index.js +3 -0
  33. package/rules/require-export/index.js +3 -0
  34. package/rules/require-import/index.js +3 -0
  35. package/rules/trim-props/index.js +3 -0
  36. package/test/a11y-prohibit-input-maxlength-attribute.js +39 -0
  37. package/test/best-practice-for-layouts.js +3 -0
  38. package/tsconfig.json +12 -0
  39. package/types.js +3 -0
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
+ ### [0.5.8](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.5.7...v0.5.8) (2024-04-09)
6
+
7
+
8
+ ### Features
9
+
10
+ * a11y-prohibit-input-maxlength-attribute ([#135](https://github.com/kufu/eslint-plugin-smarthr/issues/135)) ([9f9d010](https://github.com/kufu/eslint-plugin-smarthr/commit/9f9d010e819d936fe5f55556a8f65e6485c552ce))
11
+ * best-practice-for-layouts に <Stack align="center"> を <Center> に置き換えることを促すチェックを追加 ([#133](https://github.com/kufu/eslint-plugin-smarthr/issues/133)) ([5835530](https://github.com/kufu/eslint-plugin-smarthr/commit/58355308bf9a5d18d2d731e699c54806af969ed9))
12
+
5
13
  ### [0.5.7](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.5.6...v0.5.7) (2024-04-01)
6
14
 
7
15
 
package/README.md CHANGED
@@ -9,6 +9,7 @@
9
9
  - [a11y-input-has-name-attribute](https://github.com/kufu/eslint-plugin-smarthr/tree/main/rules/a11y-input-has-name-attribute)
10
10
  - [a11y-input-in-form-control](https://github.com/kufu/eslint-plugin-smarthr/tree/main/rules/a11y-input-in-form-control)
11
11
  - [a11y-numbered-text-within-ol](https://github.com/kufu/eslint-plugin-smarthr/tree/main/rules/a11y-numbered-text-within-ol)
12
+ - [a11y-prohibit-input-maxlength-attribute](https://github.com/kufu/eslint-plugin-smarthr/tree/main/rules/a11y-prohibit-input-maxlength-attribute)
12
13
  - [a11y-prohibit-input-placeholder](https://github.com/kufu/eslint-plugin-smarthr/tree/main/rules/a11y-prohibit-input-placeholder)
13
14
  - [a11y-prohibit-useless-sectioning-fragment](https://github.com/kufu/eslint-plugin-smarthr/tree/main/rules/a11y-prohibit-useless-sectioning-fragment)
14
15
  - [a11y-replace-unreadable-symbol](https://github.com/kufu/eslint-plugin-smarthr/tree/main/rules/a11y-replace-unreadable-symbol)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-smarthr",
3
- "version": "0.5.7",
3
+ "version": "0.5.8",
4
4
  "author": "SmartHR",
5
5
  "license": "MIT",
6
6
  "description": "A sharable ESLint plugin for SmartHR",
@@ -27,7 +27,8 @@
27
27
  "devDependencies": {
28
28
  "eslint": "^8.8.0",
29
29
  "jest": "^27.4.7",
30
- "standard-version": "^9.3.2"
30
+ "standard-version": "^9.3.2",
31
+ "typescript-eslint": "^7.5.0"
31
32
  },
32
33
  "peerDependencies": {
33
34
  "eslint": "^7 || ^8"
@@ -93,6 +93,9 @@ const SCHEMA = [
93
93
  }
94
94
  ]
95
95
 
96
+ /**
97
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
98
+ */
96
99
  module.exports = {
97
100
  meta: {
98
101
  type: 'problem',
@@ -44,6 +44,9 @@ const message = `a, buttonなどのクリッカブルな要素内にはテキス
44
44
  - SVG component の場合、altを属性として受け取れるようにした上で '<svg role="img" aria-label={alt}>' のように指定してください
45
45
  - クリッカブルな要素内に設置しているコンポーネントがテキストを含んでいる場合、"XxxxText" のように末尾に "Text" もしくは "Message" という名称を設定してください`
46
46
 
47
+ /**
48
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
49
+ */
47
50
  module.exports = {
48
51
  meta: {
49
52
  type: 'problem',
@@ -81,6 +81,9 @@ const SCHEMA = [
81
81
  }
82
82
  ]
83
83
 
84
+ /**
85
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
86
+ */
84
87
  module.exports = {
85
88
  meta: {
86
89
  type: 'problem',
@@ -62,6 +62,9 @@ const searchBubbleUp = (node) => {
62
62
  return searchBubbleUp(node.parent)
63
63
  }
64
64
 
65
+ /**
66
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
67
+ */
65
68
  module.exports = {
66
69
  meta: {
67
70
  type: 'problem',
@@ -223,6 +223,9 @@ const forInSearchChildren = (ary) => {
223
223
 
224
224
  const findTagAttr = (a) => a.name?.name == 'tag'
225
225
 
226
+ /**
227
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
228
+ */
226
229
  module.exports = {
227
230
  meta: {
228
231
  type: 'problem',
@@ -48,6 +48,9 @@ const SCHEMA = [
48
48
  }
49
49
  ]
50
50
 
51
+ /**
52
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
53
+ */
51
54
  module.exports = {
52
55
  meta: {
53
56
  type: 'problem',
@@ -40,6 +40,9 @@ const SCHEMA = [
40
40
  }
41
41
  ]
42
42
 
43
+ /**
44
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
45
+ */
43
46
  module.exports = {
44
47
  meta: {
45
48
  type: 'problem',
@@ -77,6 +77,9 @@ const SCHEMA = [
77
77
  }
78
78
  ]
79
79
 
80
+ /**
81
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
82
+ */
80
83
  module.exports = {
81
84
  meta: {
82
85
  type: 'problem',
@@ -53,6 +53,9 @@ const renderNode = (node, matcher) => node.type === 'JSXText' ? `\`${matcher[1]}
53
53
 
54
54
  const SCHEMA = []
55
55
 
56
+ /**
57
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
58
+ */
56
59
  module.exports = {
57
60
  meta: {
58
61
  type: 'problem',
@@ -0,0 +1,35 @@
1
+ # smarthr/a11y-prohibit-input-maxlength-attribute
2
+
3
+ - input, textarea 要素に maxLength 属性を設定することを禁止するルールです
4
+ - maxLength属性がついた要素に、テキストをペーストすると、maxLength属性の値を超えた範囲が意図せず切り捨てられてしまう場合があります。
5
+ - maxLength 属性ではなく、pattern 属性と title 属性を組み合わせて form 要素でラップすることで、入力時でなく、submit 時にバリデーションすることができます。
6
+
7
+ ## rules
8
+
9
+ ```js
10
+ {
11
+ rules: {
12
+ 'smarthr/a11y-prohibit-input-maxlength-attribute': [
13
+ 'error', // 'warn', 'off'
14
+ ]
15
+ },
16
+ }
17
+ ```
18
+
19
+ ## ❌ Incorrect
20
+
21
+ ```jsx
22
+ <input maxLength={30} />
23
+ <XxxInput maxLength={40} />
24
+ <textarea maxLength={50} />
25
+ <XxxTextarea maxLength={60} />
26
+ ```
27
+
28
+ ## ✅ Correct
29
+
30
+ ```jsx
31
+ <input />
32
+ <XxxInput />
33
+ <textarea />
34
+ <XxxTextarea />
35
+ ```
@@ -0,0 +1,44 @@
1
+ const { generateTagFormatter } = require('../../libs/format_styled_components')
2
+
3
+ const EXPECTED_NAMES = {
4
+ '(Input|^input)$': '(Input)$',
5
+ '(Textarea|^textarea)$': '(Textarea)$',
6
+ }
7
+
8
+ const UNEXPECTED_NAMES = EXPECTED_NAMES
9
+
10
+ const INPUT_COMPONENT_NAMES = new RegExp(`(${Object.keys(EXPECTED_NAMES).join('|')})`)
11
+
12
+ const SCHEMA = []
13
+
14
+ /**
15
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
16
+ */
17
+ module.exports = {
18
+ meta: {
19
+ type: 'problem',
20
+ schema: SCHEMA,
21
+ },
22
+ create(context) {
23
+ return {
24
+ ...generateTagFormatter({ context, EXPECTED_NAMES, UNEXPECTED_NAMES }),
25
+ JSXOpeningElement: (node) => {
26
+ if (node.name.type === 'JSXIdentifier' && INPUT_COMPONENT_NAMES.test(node.name.name)) {
27
+ const checkHasMaxLength = (attr) => attr.name?.name === 'maxLength'
28
+ const maxLengthAttr = node.attributes.find(checkHasMaxLength)
29
+ if (maxLengthAttr) {
30
+ context.report({
31
+ node,
32
+ message: `${node.name.name}にmaxLength属性を設定しないでください。
33
+ - maxLength属性がついた要素に、テキストをペーストすると、maxLength属性の値を超えた範囲が意図せず切り捨てられてしまう場合があります
34
+ - 以下のいずれかの方法で修正をおこなってください
35
+ - 方法1: pattern属性とtitle属性を組み合わせ、form要素でラップする
36
+ - 方法2: JavaScriptを用いたバリデーションを実装する`,
37
+ })
38
+ }
39
+ }
40
+ },
41
+ }
42
+ },
43
+ }
44
+ module.exports.schema = SCHEMA
@@ -9,6 +9,9 @@ const EXPECTED_NAMES = {
9
9
  'DatePicker$': 'DatePicker$',
10
10
  }
11
11
 
12
+ /**
13
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
14
+ */
12
15
  module.exports = {
13
16
  meta: {
14
17
  type: 'problem',
@@ -34,6 +34,9 @@ const searchSectioningFragment = (node) => {
34
34
 
35
35
  const SCHEMA = []
36
36
 
37
+ /**
38
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
39
+ */
37
40
  module.exports = {
38
41
  meta: {
39
42
  type: 'problem',
@@ -2,6 +2,9 @@ const TILDE_REGEX = /([~〜])/
2
2
 
3
3
  const SCHEMA = []
4
4
 
5
+ /**
6
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
7
+ */
5
8
  module.exports = {
6
9
  meta: {
7
10
  type: 'problem',
@@ -15,6 +15,9 @@ const filterFalsyJSXText = (cs) => cs.filter((c) => (
15
15
  !(c.type === 'JSXText' && c.value.match(/^\s*\n+\s*$/))
16
16
  ))
17
17
 
18
+ /**
19
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
20
+ */
18
21
  module.exports = {
19
22
  meta: {
20
23
  type: 'problem',
@@ -10,6 +10,9 @@ const findTypeAttr = (a) => a.type === 'JSXAttribute' && a.name.name === 'type'
10
10
 
11
11
  const SCHEMA = []
12
12
 
13
+ /**
14
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
15
+ */
13
16
  module.exports = {
14
17
  meta: {
15
18
  type: 'problem',
@@ -25,6 +25,9 @@ const fixAction = (fixer, node, replacedSuffix = '') => {
25
25
 
26
26
  const SCHEMA = []
27
27
 
28
+ /**
29
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
30
+ */
28
31
  module.exports = {
29
32
  meta: {
30
33
  type: 'problem',
@@ -25,6 +25,7 @@ const checkFalsyJSXText = (c) => (
25
25
  )
26
26
 
27
27
  const findJustifyAttr = (a) => a.name?.name === 'justify'
28
+ const findAlignAttr = (a) => a.name?.name === 'align'
28
29
 
29
30
  const searchChildren = (node) => {
30
31
  if (
@@ -55,6 +56,9 @@ const searchChildren = (node) => {
55
56
 
56
57
  const SCHEMA = []
57
58
 
59
+ /**
60
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
61
+ */
58
62
  module.exports = {
59
63
  meta: {
60
64
  type: 'problem',
@@ -80,11 +84,17 @@ module.exports = {
80
84
  return
81
85
  }
82
86
 
87
+ const alignAttr = layoutType === 'Stack' ? node.attributes.find(findAlignAttr) : null
88
+
89
+ if (alignAttr && FLEX_END_REGEX.test(alignAttr.value.value)) {
90
+ return
91
+ }
92
+
83
93
  if (searchChildren(children[0])) {
84
94
  context.report({
85
95
  node,
86
96
  message:
87
- justifyAttr && justifyAttr.value.value === 'center'
97
+ (justifyAttr && justifyAttr.value.value === 'center' || alignAttr && alignAttr.value.value === 'center')
88
98
  ? `${nodeName} は smarthr-ui/${layoutType} ではなく smarthr-ui/Center でマークアップしてください`
89
99
  : `${nodeName}には子要素が一つしか無いため、${layoutType}でマークアップする意味がありません。
90
100
  - styleを確認し、div・spanなど、別要素でマークアップし直すか、${nodeName}を削除してください
@@ -8,6 +8,9 @@ const EXPECTED_NAMES = {
8
8
  const REGEX_REMOTE_TRIGGER_DIALOG = /RemoteTrigger(Action|Message|Modeless)Dialog$/
9
9
  const REGEX_REMOTE_DIALOG_TRIGGER = /RemoteDialogTrigger$/
10
10
 
11
+ /**
12
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
13
+ */
11
14
  module.exports = {
12
15
  meta: {
13
16
  type: 'suggestion',
@@ -79,6 +79,9 @@ const calculateRelativeImportPath = ({ importPath, filteredDirs, filteredPaths }
79
79
  return `${filteredDirs.length === 0 ? './' : [...Array(filteredDirs.length)].reduce((prev) => `${prev}../`, '')}${filteredPaths.join('/')}`.replace(/^(.+?)\/$/, '$1')
80
80
  }
81
81
 
82
+ /**
83
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
84
+ */
82
85
  module.exports = {
83
86
  meta: {
84
87
  type: 'suggestion',
@@ -13,6 +13,9 @@ const SCHEMA = [
13
13
  }
14
14
  ]
15
15
 
16
+ /**
17
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
18
+ */
16
19
  module.exports = {
17
20
  meta: {
18
21
  type: 'suggestion',
@@ -8,6 +8,9 @@ const SCHEMA = [
8
8
  }
9
9
  ]
10
10
 
11
+ /**
12
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
13
+ */
11
14
  module.exports = {
12
15
  meta: {
13
16
  type: 'problem',
@@ -33,6 +33,9 @@ const SCHEMA = [
33
33
  }
34
34
  ]
35
35
 
36
+ /**
37
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
38
+ */
36
39
  module.exports = {
37
40
  meta: {
38
41
  type: 'suggestion',
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
3
+ */
1
4
  module.exports = {
2
5
  meta: {
3
6
  type: 'suggestion',
@@ -9,6 +9,9 @@ const SCHEMA = [{
9
9
  }]
10
10
 
11
11
 
12
+ /**
13
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
14
+ */
12
15
  module.exports = {
13
16
  meta: {
14
17
  type: 'suggestion',
@@ -32,6 +32,9 @@ const SCHEMA = [{
32
32
 
33
33
  const defaultReportMessage = (moduleName, exportName) => `${moduleName}${typeof exportName == 'string' ? `/${exportName}`: ''} は利用しないでください`
34
34
 
35
+ /**
36
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
37
+ */
35
38
  module.exports = {
36
39
  meta: {
37
40
  type: 'suggestion',
@@ -26,6 +26,9 @@ const SCHEMA = [
26
26
  },
27
27
  ]
28
28
 
29
+ /**
30
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
31
+ */
29
32
  module.exports = {
30
33
  meta: {
31
34
  type: 'suggestion',
@@ -83,6 +83,9 @@ const calculateReplacedImportPath = (source) => {
83
83
  const pickImportedName = (s) => s.imported?.name
84
84
  const findExistsSync = (p) => fs.existsSync(p)
85
85
 
86
+ /**
87
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
88
+ */
86
89
  module.exports = {
87
90
  meta: {
88
91
  type: 'suggestion',
@@ -40,6 +40,9 @@ const useRegex = (use) => {
40
40
  return new RegExp(`((${codeSeparator}(${actualUse})${codeSeparator})|(^(${actualUse})${codeSeparator})|${codeSeparator}(${actualUse})$)`)
41
41
  }
42
42
 
43
+ /**
44
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
45
+ */
43
46
  module.exports = {
44
47
  meta: {
45
48
  type: 'suggestion',
@@ -20,6 +20,9 @@ const fetchEdgeDeclaration = (node) => {
20
20
  return fetchEdgeDeclaration(declaration)
21
21
  }
22
22
 
23
+ /**
24
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
25
+ */
23
26
  module.exports = {
24
27
  meta: {
25
28
  type: 'suggestion',
@@ -32,6 +32,9 @@ const SCHEMA = [{
32
32
 
33
33
  const defaultReportMessage = (moduleName, exportName) => `${moduleName}${typeof exportName == 'string' ? `/${exportName}`: ''} をimportしてください`
34
34
 
35
+ /**
36
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
37
+ */
35
38
  module.exports = {
36
39
  meta: {
37
40
  type: 'suggestion',
@@ -1,3 +1,6 @@
1
+ /**
2
+ * @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
3
+ */
1
4
  module.exports = {
2
5
  meta: {
3
6
  type: 'suggestion',
@@ -0,0 +1,39 @@
1
+ const rule = require('../rules/a11y-prohibit-input-maxlength-attribute')
2
+ const RuleTester = require('eslint').RuleTester
3
+
4
+ const ruleTester = new RuleTester({
5
+ parserOptions: {
6
+ ecmaVersion: 12,
7
+ ecmaFeatures: {
8
+ experimentalObjectRestSpread: true,
9
+ jsx: true,
10
+ },
11
+ sourceType: 'module',
12
+ },
13
+ })
14
+
15
+ const expectedErrorMessage = (elName) => `${elName}にmaxLength属性を設定しないでください。
16
+ - maxLength属性がついた要素に、テキストをペーストすると、maxLength属性の値を超えた範囲が意図せず切り捨てられてしまう場合があります
17
+ - 以下のいずれかの方法で修正をおこなってください
18
+ - 方法1: pattern属性とtitle属性を組み合わせ、form要素でラップする
19
+ - 方法2: JavaScriptを用いたバリデーションを実装する`
20
+
21
+ ruleTester.run('a11y-prohibit-input-maxlength-attribute', rule, {
22
+ valid: [
23
+ { code: `<input />` },
24
+ { code: `<Input type="text" />` },
25
+ { code: `<HogeInput value="hoge" />` },
26
+ { code: `<textarea>hoge</textarea>` },
27
+ { code: `<Textarea type="text" />` },
28
+ { code: `<HogeTextarea value="hoge" />` },
29
+ { code: `<><input /></>`}
30
+ ],
31
+ invalid: [
32
+ { code: `<input maxLength={30} />`, errors: [{ message: expectedErrorMessage('input') }] },
33
+ { code: `<Input type="text" maxLength={40} />`, errors: [{ message: expectedErrorMessage('Input') }] },
34
+ { code: `<HogeInput maxLength value="hoge" />`, errors: [{ message: expectedErrorMessage('HogeInput') }] },
35
+ { code: `<textarea maxLength={50}>hoge</textarea>`, errors: [{ message: expectedErrorMessage('textarea') }]},
36
+ { code: `<Textarea type="text" maxLength={60} />`, errors: [{ message: expectedErrorMessage('Textarea') }]},
37
+ { code: `<HogeTextarea maxLength={70} value="hoge" />`, errors: [{ message: expectedErrorMessage('HogeTextarea') }]}
38
+ ]
39
+ })
@@ -55,6 +55,8 @@ ruleTester.run('best-practice-for-button-element', rule, {
55
55
  { code: `<AnyCluster>{a ? <Hoge /> : a ? <Hoge /> : a.b.map(action)}</AnyCluster>` },
56
56
  { code: `<Cluster justify="flex-end">{a}</Cluster>` },
57
57
  { code: `<HogeCluster justify="end">{a}</HogeCluster>` },
58
+ { code: `<Stack align="flex-end">{a}</Stack>` },
59
+ { code: `<HogeStack align="end">{a}</HogeStack>` },
58
60
  ],
59
61
  invalid: [
60
62
  { code: `<Stack><Hoge /></Stack>`, errors: [ { message: errorMessage('Stack', 'Stack') } ] },
@@ -82,6 +84,7 @@ ruleTester.run('best-practice-for-button-element', rule, {
82
84
  { code: `<AnyCluster>{a ? <Hoge /> : a.b.hoge(action)}</AnyCluster>`, errors: [ { message: errorMessage('Cluster', 'AnyCluster') } ] },
83
85
  { code: `<AnyCluster>{a ? <Hoge /> : a ? <Hoge /> : a.b.hoge(action)}</AnyCluster>`, errors: [ { message: errorMessage('Cluster', 'AnyCluster') } ] },
84
86
  { code: `<HogeCluster justify="center">{a}</HogeCluster>`, errors: [ { message: 'HogeCluster は smarthr-ui/Cluster ではなく smarthr-ui/Center でマークアップしてください' } ] },
87
+ { code: `<HogeStack align="center">{a}</HogeStack>`, errors: [ { message: 'HogeStack は smarthr-ui/Stack ではなく smarthr-ui/Center でマークアップしてください' } ] },
85
88
  ]
86
89
  })
87
90
 
package/tsconfig.json ADDED
@@ -0,0 +1,12 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strict": true,
4
+ "allowJs": true,
5
+ "checkJs": true,
6
+ "noEmit": true,
7
+ "target": "ESNext",
8
+ "module": "CommonJS",
9
+ "lib": ["ESNext"],
10
+ "noImplicitAny": true
11
+ },
12
+ }
package/types.js ADDED
@@ -0,0 +1,3 @@
1
+ /**
2
+ * @typedef {import('@typescript-eslint/utils').TSESTree.JSXOpeningElement} JSXOpeningElement
3
+ */