eslint-plugin-smarthr 0.2.2 → 0.2.5

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,28 @@
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.2.5](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.2.4...v0.2.5) (2022-09-08)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * require-import, prohibit-import: report message の一部でテンプレート文字列がそのまま出力されてしまう事があるバグを修正 ([#29](https://github.com/kufu/eslint-plugin-smarthr/issues/29)) ([b805f90](https://github.com/kufu/eslint-plugin-smarthr/commit/b805f90cd39b1aa4b95cbfbd983c5ff1c61f8afe))
11
+ * 画像系コンポーネントが代替テキスト属性を持つかチェックする際にエラーになるパターンを修正 ([#30](https://github.com/kufu/eslint-plugin-smarthr/issues/30)) ([bcd1044](https://github.com/kufu/eslint-plugin-smarthr/commit/bcd1044d7532531015a279520ed8eda582227492))
12
+
13
+ ### [0.2.4](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.2.3...v0.2.4) (2022-08-30)
14
+
15
+
16
+ ### Features
17
+
18
+ * ruleを更新する ([#27](https://github.com/kufu/eslint-plugin-smarthr/issues/27)) ([1ec7783](https://github.com/kufu/eslint-plugin-smarthr/commit/1ec7783395c9dafa547c453724f3671df489997b))
19
+
20
+ ### [0.2.3](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.2.2...v0.2.3) (2022-08-26)
21
+
22
+
23
+ ### Bug Fixes
24
+
25
+ * a11y-xxxx: styled(Hoge)の実行結果を変数に代入しないパターンに対応する ([#26](https://github.com/kufu/eslint-plugin-smarthr/issues/26)) ([0bb0259](https://github.com/kufu/eslint-plugin-smarthr/commit/0bb02595a3be35802c1fe8bc41011fd1e55bf319))
26
+
5
27
  ### [0.2.2](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.2.1...v0.2.2) (2022-08-18)
6
28
 
7
29
 
package/libs/common.js CHANGED
@@ -28,7 +28,7 @@ const rootPath = (() => {
28
28
  return ''
29
29
  }
30
30
 
31
- const p = (replacePaths['@/'] || [])[0]
31
+ const p = (replacePaths['@/'] || replacePaths['~/'] || [])[0]
32
32
 
33
33
  if (!p) {
34
34
  return ''
@@ -1,3 +1,31 @@
1
+ const getExtendedComponentName = (node) => {
2
+ if (!node.parent) {
3
+ return null
4
+ }
5
+
6
+ return node.parent.id?.name || getExtendedComponentName(node.parent)
7
+ }
8
+ const getBaseComponentName = (node) => {
9
+ if (!node) {
10
+ return null
11
+ }
12
+
13
+ if (node.type === 'CallExpression') {
14
+ if (node.callee.name === 'styled') {
15
+ return node.arguments[0].name
16
+ }
17
+ if (node.callee.object?.name === 'styled') {
18
+ return node.callee.property.name
19
+ }
20
+ }
21
+
22
+ if (node?.object?.name === 'styled') {
23
+ return node.property.name
24
+ }
25
+
26
+ return getBaseComponentName(node.parent)
27
+ }
28
+
1
29
  const generateTagFormatter = ({ context, EXPECTED_NAMES }) => ({
2
30
  ImportDeclaration: (node) => {
3
31
  if (node.source.value !== 'styled-components') {
@@ -17,40 +45,29 @@ const generateTagFormatter = ({ context, EXPECTED_NAMES }) => ({
17
45
  }
18
46
  },
19
47
  TaggedTemplateExpression: (node) => {
20
- const { tag } = node
21
- const base = (() => {
22
- if (tag.type === 'CallExpression' && tag.callee.name === 'styled') {
23
- return tag.arguments[0].name
24
- }
25
-
26
- if (tag?.object?.name === 'styled') {
27
- return tag.property.name
28
- }
48
+ const extended = getExtendedComponentName(node)
29
49
 
30
- return null
31
- })()
50
+ if (extended) {
51
+ const base = getBaseComponentName(node.tag)
32
52
 
33
- if (!base) {
34
- return
35
- }
53
+ if (base) {
54
+ Object.entries(EXPECTED_NAMES).forEach(([b, e]) => {
55
+ if (base.match(new RegExp(b))) {
56
+ const extendedregex = new RegExp(e)
36
57
 
37
- const extended = node.parent.id.name
38
-
39
- Object.entries(EXPECTED_NAMES).forEach(([b, e]) => {
40
- if (base.match(new RegExp(b))) {
41
- const extendedregex = new RegExp(e)
42
-
43
- if (!extended.match(extendedregex)) {
44
- context.report({
45
- node: node.parent,
46
- messageId: 'format-styled-components',
47
- data: {
48
- message: `${extended}を正規表現 "${extendedregex.toString()}" がmatchする名称に変更してください`,
49
- },
50
- });
51
- }
58
+ if (!extended.match(extendedregex)) {
59
+ context.report({
60
+ node: node.parent,
61
+ messageId: 'format-styled-components',
62
+ data: {
63
+ message: `${extended}を正規表現 "${extendedregex.toString()}" がmatchする名称に変更してください`,
64
+ },
65
+ });
66
+ }
67
+ }
68
+ })
52
69
  }
53
- })
70
+ }
54
71
  },
55
72
  })
56
73
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eslint-plugin-smarthr",
3
- "version": "0.2.2",
3
+ "version": "0.2.5",
4
4
  "author": "SmartHR",
5
5
  "license": "MIT",
6
6
  "description": "A sharable ESLint plugin for SmartHR",
@@ -1,6 +1,7 @@
1
1
  const { generateTagFormatter } = require('../../libs/format_styled_components')
2
2
 
3
3
  const EXPECTED_NAMES = {
4
+ 'SmartHRLogo$': 'SmartHRLogo$',
4
5
  '(b|B)utton$': 'Button$',
5
6
  'Anchor$': 'Anchor$',
6
7
  'Link$': 'Link$',
@@ -41,7 +42,18 @@ module.exports = {
41
42
  }
42
43
 
43
44
  if (c.type === 'JSXElement') {
44
- if (c.openingElement.attributes.some((a) => (['visuallyHiddenText', 'alt'].includes(a.name.name) && !!a.value.value))) {
45
+ // // HINT: SmartHRLogo コンポーネントは内部でaltを持っているため対象外にする
46
+ if (c.openingElement.name.name.match(/SmartHRLogo$/)) {
47
+ return true
48
+ }
49
+
50
+ if (c.openingElement.attributes.some((a) => {
51
+ if (!['visuallyHiddenText', 'alt'].includes(a.name.name)) {
52
+ return false
53
+ }
54
+
55
+ return (!!a.value.value || a.value.type === 'JSXExpressionContainer')
56
+ })) {
45
57
  return true
46
58
  }
47
59
 
@@ -21,7 +21,7 @@ module.exports = {
21
21
  ...generateTagFormatter({ context, EXPECTED_NAMES }),
22
22
  JSXOpeningElement: (node) => {
23
23
  if ((node.name.name || '').match(/(img|image)$/i)) { // HINT: Iconは別途テキストが存在する場合が多いためチェックの対象外とする
24
- const alt = node.attributes.find((a) => a.name.name === 'alt')
24
+ const alt = node.attributes.find((a) => a.name?.name === 'alt')
25
25
 
26
26
  let message = ''
27
27
 
@@ -47,7 +47,21 @@ module.exports = {
47
47
  return
48
48
  }
49
49
 
50
- filterFalsyJSXText(parentNode.children).forEach((c) => {
50
+ const children = filterFalsyJSXText(parentNode.children)
51
+
52
+ if (children.length > 1) {
53
+ context.report({
54
+ node,
55
+ messageId: 'a11y-trigger-has-button',
56
+ data: {
57
+ message: `${match[1]}Trigger の直下には複数のコンポーネントを設置することは出来ません。buttonコンポーネントが一つだけ設置されている状態にしてください`,
58
+ },
59
+ })
60
+
61
+ return
62
+ }
63
+
64
+ children.forEach((c) => {
51
65
  // `<DialogTrigger>{button}</DialogTrigger>` のような場合は許可する
52
66
  if (c.type === 'JSXExpressionContainer') {
53
67
  return false
@@ -56,7 +70,7 @@ module.exports = {
56
70
  if (
57
71
  c.type !== 'JSXElement' ||
58
72
  !c.openingElement.name.name.match(/(b|B)utton$/) ||
59
- c.openingElement.name.name.match(/AnchorButton?/)
73
+ c.openingElement.name.name.match(/AnchorButton$/)
60
74
  ) {
61
75
  context.report({
62
76
  node: c,
@@ -7,7 +7,7 @@
7
7
 
8
8
  ## config
9
9
 
10
- - tsconfig.json の compilerOptions.pathsに '@/*' としてroot path を指定する必要があります
10
+ - tsconfig.json の compilerOptions.pathsに '@/*', もしくは '~/*' としてroot path を指定する必要があります
11
11
  - ドメインを識別するために以下の設定を記述する必要があります
12
12
  - globalModuleDir
13
13
  - 全体で利用するファイルを収めているディレクトリを相対パスで指定します
@@ -6,7 +6,7 @@
6
6
 
7
7
  ## config
8
8
 
9
- - tsconfig.json の compilerOptions.pathsに '@/*' としてroot path を指定する必要があります
9
+ - tsconfig.json の compilerOptions.pathsに '@/*', もしくは '~/*' としてroot path を指定する必要があります
10
10
  - ドメインを識別するために以下の設定を記述する必要があります
11
11
  - globalModuleDir
12
12
  - 全体で利用するファイルを収めているディレクトリを相対パスで指定します
@@ -90,7 +90,7 @@ module.exports = {
90
90
  node,
91
91
  messageId: 'prohibit_import',
92
92
  data: {
93
- message: reportMessage ? reportMessage.replace('{{module}}', node.source.value).replace('{{export}}', useImported) : defaultReportMessage(node.source.value, useImported)
93
+ message: reportMessage ? reportMessage.replaceAll('{{module}}', node.source.value).replaceAll('{{export}}', useImported) : defaultReportMessage(node.source.value, useImported)
94
94
  },
95
95
  });
96
96
  }
@@ -5,7 +5,7 @@
5
5
 
6
6
  ## config
7
7
 
8
- - tsconfig.json の compilerOptions.pathsに '@/*' としてroot path を指定する必要があります
8
+ - tsconfig.json の compilerOptions.pathsに '@/*', もしくは '~/*' としてroot path を指定する必要があります
9
9
  - 以下の設定を行えます。全て省略可能です。
10
10
  - ignoreKeywords
11
11
  - ディレクトリ名から生成されるキーワードに含めたくない文字列を指定します
@@ -16,7 +16,6 @@ const DEFAULT_CONFIG = {
16
16
  ],
17
17
  SUFFIX: ['Props', 'Type'],
18
18
  },
19
- typeProperty: COMMON_DEFAULT_CONFIG,
20
19
  file: COMMON_DEFAULT_CONFIG,
21
20
  property: COMMON_DEFAULT_CONFIG,
22
21
  function: COMMON_DEFAULT_CONFIG,
@@ -62,7 +61,6 @@ const SCHEMA = [
62
61
  ...DEFAULT_SCHEMA_PROPERTY,
63
62
  suffix: { type: 'array', items: { type: 'string' } },
64
63
  },
65
- typeProperty: DEFAULT_SCHEMA_PROPERTY,
66
64
  file: DEFAULT_SCHEMA_PROPERTY,
67
65
  property: DEFAULT_SCHEMA_PROPERTY,
68
66
  function: DEFAULT_SCHEMA_PROPERTY,
@@ -89,7 +87,6 @@ const generateRedundantKeywords = ({ args, key, terminalImportName }) => {
89
87
  const option = args.option[key] || {}
90
88
  const ignoreKeywords = option.ignoreKeywords || DEFAULT_CONFIG[key].IGNORE_KEYWORDS
91
89
  const terminalImportKeyword = terminalImportName ? terminalImportName.toLowerCase() : ''
92
-
93
90
  return args.keywords.reduce((prev, keyword) => {
94
91
  if (keyword === terminalImportKeyword || ignoreKeywords.includes(keyword)) {
95
92
  return prev
@@ -262,8 +259,7 @@ const generateTypeRedundant = (args) => {
262
259
  }
263
260
 
264
261
  const generateTypePropertyRedundant = (args) => {
265
- const key = 'typeProperty'
266
-
262
+ const key = 'property'
267
263
  return handleReportBetterName({
268
264
  ...args,
269
265
  key,
@@ -274,7 +270,7 @@ const generateTypePropertyRedundant = (args) => {
274
270
  })
275
271
  }
276
272
  const generateTypePropertyFunctionParamsRedundant = (args) => {
277
- const key = 'typeProperty'
273
+ const key = 'property'
278
274
  const redundant = handleReportBetterName({
279
275
  ...args,
280
276
  key,
@@ -298,7 +294,15 @@ const generatePropertyRedundant = (args) => {
298
294
  option: args.option[key],
299
295
  redundantKeywords: generateRedundantKeywords({ args, key }),
300
296
  defaultBetterName: 'item',
301
- fetchName: (node) => node.key.name,
297
+ fetchName: (node) => {
298
+ // argumentsとしてわたされたobjectの展開などの場合は許可する
299
+ // このファイル内で修正すべき場合などは冗長な名前を修正するべき場合はtype propertyなどで判断出来る
300
+ if (node.parent.type === 'ObjectPattern') {
301
+ return null
302
+ }
303
+
304
+ return node.key.name
305
+ },
302
306
  })
303
307
  }
304
308
 
@@ -391,7 +395,6 @@ module.exports = {
391
395
  'file-name': ' {{ message }}',
392
396
  'type-name': '{{ message }}',
393
397
  'type-name/invalid-suffix': '{{ message }}',
394
- 'typeProperty-name': '{{ message }}',
395
398
  'property-name': ' {{ message }}',
396
399
  'function-name': ' {{ message }}',
397
400
  'functionParams-name': ' {{ message }}',
@@ -403,7 +406,7 @@ module.exports = {
403
406
  },
404
407
  create(context) {
405
408
  if (!rootPath) {
406
- throw new Error('tsconfig.json の compilerOptions.paths に `"@/*": ["any_path/*"]` 形式でフロントエンドのroot dir を指定してください')
409
+ throw new Error('tsconfig.json の compilerOptions.paths に `@/*`、もしくは `~/*` 形式でフロントエンドのroot dir を指定してください(例: `"@/*": ["./any_path/*"]`)')
407
410
  }
408
411
 
409
412
  let rules = {}
@@ -449,9 +452,10 @@ module.exports = {
449
452
  addRule('TSTypeAliasDeclaration', generateTypeRedundant(args))
450
453
  // addRule('TSInterfaceDeclaration', generateTypeRedundant(args)) // 必要になったら実装する
451
454
  }
452
- if (option.typeProperty) {
455
+ if (option.property) {
453
456
  const typePropRedundant = generateTypePropertyRedundant(args)
454
457
  const typeFuncParamRedundant = generateTypePropertyFunctionParamsRedundant(args)
458
+ const redundant = generatePropertyRedundant(args)
455
459
 
456
460
  addRule('TSPropertySignature', (node) => {
457
461
  typePropRedundant(node)
@@ -460,10 +464,6 @@ module.exports = {
460
464
  typeFuncParamRedundant(node.typeAnnotation.typeAnnotation)
461
465
  }
462
466
  })
463
- }
464
- if (option.property) {
465
- const redundant = generatePropertyRedundant(args)
466
-
467
467
  addRule('Property', redundant)
468
468
  addRule('PropertyDefinition', redundant)
469
469
  }
@@ -1,6 +1,6 @@
1
1
  # smarthr/require-barrel-import
2
2
 
3
- - tsconfig.json の compilerOptions.pathsに '@/*' としてroot path を指定する必要があります
3
+ - tsconfig.json の compilerOptions.pathsに '@/*', もしくは '~/*' としてroot path を指定する必要があります
4
4
  - importした対象が本来exportされているべきであるbarrel(index.tsなど)が有る場合、import pathの変更を促します
5
5
  - 例: Page/parts/Menu/Item の import は Page/parts/Menu から行わせたい
6
6
  - ディレクトリ内のindexファイルを捜査し、対象を決定します
@@ -104,7 +104,7 @@ module.exports = {
104
104
  sourceValue = sources.join('/')
105
105
  }
106
106
 
107
- if (barrel) {
107
+ if (barrel && !barrel.match(new RegExp(`^${rootPath}/index\.`))) {
108
108
  barrel = calculateReplacedImportPath(barrel)
109
109
 
110
110
  context.report({
@@ -83,7 +83,7 @@ module.exports = {
83
83
  node,
84
84
  messageId: 'require_import',
85
85
  data: {
86
- message: reportMessage ? reportMessage.replace('{{module}}', actualTarget).replace('{{export}}', item) : defaultReportMessage(actualTarget, item)
86
+ message: reportMessage ? reportMessage.replaceAll('{{module}}', actualTarget).replaceAll('{{export}}', item) : defaultReportMessage(actualTarget, item)
87
87
  },
88
88
  })
89
89
  }
@@ -26,6 +26,7 @@ ruleTester.run('a11y-clickable-element-has-text', rule, {
26
26
  { code: 'const HogeLink = styled(Link)``' },
27
27
  { code: 'const HogeButton = styled(Button)``' },
28
28
  { code: 'const FugaAnchor = styled(HogeAnchor)``' },
29
+ { code: 'const FugaSmartHRLogo = styled(SmartHRLogo)``' },
29
30
  {
30
31
  code: `<a>ほげ</a>`,
31
32
  },
@@ -89,6 +90,12 @@ ruleTester.run('a11y-clickable-element-has-text', rule, {
89
90
  {
90
91
  code: `<a><span>{any}</span></a>`,
91
92
  },
93
+ {
94
+ code: `<a><SmartHRLogo /></a>`,
95
+ },
96
+ {
97
+ code: `<a><PrefixSmartHRLogo /></a>`,
98
+ },
92
99
  ],
93
100
  invalid: [
94
101
  { code: `import hoge from 'styled-components'`, errors: [ { message: "styled-components をimportする際は、名称が`styled` となるようにしてください。例: `import styled from 'styled-components'`" } ] },
@@ -98,6 +105,8 @@ ruleTester.run('a11y-clickable-element-has-text', rule, {
98
105
  { code: 'const Hoge = styled(Link)``', errors: [ { message: `Hogeを正規表現 "/Link$/" がmatchする名称に変更してください` } ] },
99
106
  { code: 'const Hoge = styled(Button)``', errors: [ { message: `Hogeを正規表現 "/Button$/" がmatchする名称に変更してください` } ] },
100
107
  { code: 'const Fuga = styled(HogeAnchor)``', errors: [ { message: `Fugaを正規表現 "/Anchor$/" がmatchする名称に変更してください` } ] },
108
+ { code: 'const Fuga = styled(HogeAnchor)``', errors: [ { message: `Fugaを正規表現 "/Anchor$/" がmatchする名称に変更してください` } ] },
109
+ { code: 'const Fuga = styled(SmartHRLogo)``', errors: [ { message: `Fugaを正規表現 "/SmartHRLogo$/" がmatchする名称に変更してください` } ] },
101
110
  {
102
111
  code: `<a><img src="hoge.jpg" /></a>`,
103
112
  errors: [{ message: defaultErrorMessage }]
@@ -138,5 +147,9 @@ ruleTester.run('a11y-clickable-element-has-text', rule, {
138
147
  code: `<button><AnyComponent><Icon visuallyHiddenText="" /></AnyComponent></button>`,
139
148
  errors: [{ message: defaultErrorMessage }]
140
149
  },
150
+ {
151
+ code: `<button><SmartHRLogoSuffix /></button>`,
152
+ errors: [{ message: defaultErrorMessage }]
153
+ },
141
154
  ]
142
155
  })
@@ -33,18 +33,20 @@ ruleTester.run('a11y-trigger-has-button', rule, {
33
33
  ],
34
34
  invalid: [
35
35
  { code: `import hoge from 'styled-components'`, errors: [ { message: "styled-components をimportする際は、名称が`styled` となるようにしてください。例: `import styled from 'styled-components'`" } ] },
36
- { code: 'const Hoge = styled.button``', errors: [ { message: `Hogeを正規表現 "/Button$/" がmatchする名称に変更してください` } ] },
37
- { code: 'const Hoge = styled.a``', errors: [ { message: `Hogeを正規表現 "/(Anchor|Link)$/" がmatchする名称に変更してください` } ] },
38
- { code: 'const Hoge = styled(Button)``', errors: [ { message: `Hogeを正規表現 "/Button$/" がmatchする名称に変更してください` } ] },
39
- { code: 'const Hoge = styled(AnchorButton)``', errors: [ { message: `Hogeを正規表現 "/Button$/" がmatchする名称に変更してください` },{ message: `Hogeを正規表現 "/AnchorButton$/" がmatchする名称に変更してください` } ] },
40
- { code: 'const Hoge = styled(ButtonAnchor)``', errors: [ { message: `Hogeを正規表現 "/ButtonAnchor$/" がmatchする名称に変更してください` }, { message: `Hogeを正規表現 "/Anchor$/" がmatchする名称に変更してください` } ] },
41
- { code: 'const Hoge = styled(Anchor)``', errors: [ { message: `Hogeを正規表現 "/Anchor$/" がmatchする名称に変更してください` } ] },
42
- { code: 'const Hoge = styled(Link)``', errors: [ { message: `Hogeを正規表現 "/Link$/" がmatchする名称に変更してください` } ] },
43
- { code: 'const Hoge = styled(DropdownTrigger)``', errors: [ { message: `Hogeを正規表現 "/DropdownTrigger$/" がmatchする名称に変更してください` } ] },
44
- { code: 'const Hoge = styled(DialogTrigger)``', errors: [ { message: `Hogeを正規表現 "/DialogTrigger$/" がmatchする名称に変更してください` } ] },
45
- { code: '<DropdownTrigger>ほげ</DropdownTrigger>', errors: [ { message: 'DropdownTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
46
- { code: '<DialogTrigger><span><Button>ほげ</Button></span></DialogTrigger>', errors: [ { message: 'DialogTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
47
- { code: '<DropdownTrigger><AnchorButton>ほげ</AnchorButton></DropdownTrigger>', errors: [ { message: 'DropdownTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
48
- { code: '<DropdownTrigger><ButtonAnchor>ほげ</ButtonAnchor></DropdownTrigger>', errors: [ { message: 'DropdownTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
36
+ { code: 'const Hoge = styled.button``', errors: [ { message: `Hogeを正規表現 "/Button$/" がmatchする名称に変更してください` } ] },
37
+ { code: 'const Hoge = styled.a``', errors: [ { message: `Hogeを正規表現 "/(Anchor|Link)$/" がmatchする名称に変更してください` } ] },
38
+ { code: 'const Hoge = styled(Button)``', errors: [ { message: `Hogeを正規表現 "/Button$/" がmatchする名称に変更してください` } ] },
39
+ { code: 'const Hoge = styled(AnchorButton)``', errors: [ { message: `Hogeを正規表現 "/Button$/" がmatchする名称に変更してください` },{ message: `Hogeを正規表現 "/AnchorButton$/" がmatchする名称に変更してください` } ] },
40
+ { code: 'const Hoge = styled(ButtonAnchor)``', errors: [ { message: `Hogeを正規表現 "/ButtonAnchor$/" がmatchする名称に変更してください` }, { message: `Hogeを正規表現 "/Anchor$/" がmatchする名称に変更してください` } ] },
41
+ { code: 'const Hoge = styled(Anchor)``', errors: [ { message: `Hogeを正規表現 "/Anchor$/" がmatchする名称に変更してください` } ] },
42
+ { code: 'const Hoge = styled(Link)``', errors: [ { message: `Hogeを正規表現 "/Link$/" がmatchする名称に変更してください` } ] },
43
+ { code: 'const Hoge = styled(DropdownTrigger)``', errors: [ { message: `Hogeを正規表現 "/DropdownTrigger$/" がmatchする名称に変更してください` } ] },
44
+ { code: 'const Hoge = styled(DialogTrigger)``', errors: [ { message: `Hogeを正規表現 "/DialogTrigger$/" がmatchする名称に変更してください` } ] },
45
+ { code: '<DropdownTrigger>ほげ</DropdownTrigger>', errors: [ { message: 'DropdownTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
46
+ { code: '<DialogTrigger><span><Button>ほげ</Button></span></DialogTrigger>', errors: [ { message: 'DialogTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
47
+ { code: '<DropdownTrigger><AnchorButton>ほげ</AnchorButton></DropdownTrigger>', errors: [ { message: 'DropdownTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
48
+ { code: '<DropdownTrigger><ButtonAnchor>ほげ</ButtonAnchor></DropdownTrigger>', errors: [ { message: 'DropdownTrigger の直下にはbuttonコンポーネントのみ設置してください' } ] },
49
+ { code: '<DialogTrigger><button>{hoge}</button>{hoge}</DialogTrigger>', errors: [ { message: 'DialogTrigger の直下には複数のコンポーネントを設置することは出来ません。buttonコンポーネントが一つだけ設置されている状態にしてください' } ] },
50
+ { code: '<DropdownTrigger>{hoge}<span>text</span></DropdownTrigger>', errors: [ { message: 'DropdownTrigger の直下には複数のコンポーネントを設置することは出来ません。buttonコンポーネントが一つだけ設置されている状態にしてください' } ] },
49
51
  ]
50
52
  })