eslint-plugin-smarthr 3.5.1 → 4.0.1
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 +18 -0
- package/README.md +1 -1
- package/package.json +3 -3
- package/rules/best-practice-for-spread-syntax/README.md +116 -0
- package/rules/best-practice-for-spread-syntax/index.js +99 -0
- package/test/best-practice-for-spread-syntax.js +63 -0
- package/rules/jsx-start-with-spread-attributes/README.md +0 -31
- package/rules/jsx-start-with-spread-attributes/index.js +0 -69
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,24 @@
|
|
|
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
|
+
## [4.0.1](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v4.0.0...eslint-plugin-smarthr-v4.0.1) (2026-01-04)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Bug Fixes
|
|
9
|
+
|
|
10
|
+
* **best-practice-for-spread-syntax:** 関数に対してspread syntaxで引数を渡すパターンが誤検知される問題を修正 ([#999](https://github.com/kufu/tamatebako/issues/999)) ([3f4a163](https://github.com/kufu/tamatebako/commit/3f4a163b183305922651612d7945434dcb5fa991))
|
|
11
|
+
|
|
12
|
+
## [4.0.0](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v3.5.1...eslint-plugin-smarthr-v4.0.0) (2026-01-04)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### ⚠ BREAKING CHANGES
|
|
16
|
+
|
|
17
|
+
* **jsx-start-with-spread-attributes:** best-practice-for-spread-syntaxにrenameし、objectに展開する場合もチェックするように修正 ([#992](https://github.com/kufu/tamatebako/issues/992))
|
|
18
|
+
|
|
19
|
+
### Features
|
|
20
|
+
|
|
21
|
+
* **jsx-start-with-spread-attributes:** best-practice-for-spread-syntaxにrenameし、objectに展開する場合もチェックするように修正 ([#992](https://github.com/kufu/tamatebako/issues/992)) ([b5cde40](https://github.com/kufu/tamatebako/commit/b5cde40cc85e74babe76cd00c4b639d91e142abc))
|
|
22
|
+
|
|
5
23
|
## [3.5.1](https://github.com/kufu/tamatebako/compare/eslint-plugin-smarthr-v3.5.0...eslint-plugin-smarthr-v3.5.1) (2025-12-31)
|
|
6
24
|
|
|
7
25
|
|
package/README.md
CHANGED
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
- [design-system-guideline-prohibit-double-icons](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/design-system-guideline-prohibit-double-icons)
|
|
32
32
|
- [format-import-path](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/format-import-path)
|
|
33
33
|
- [format-translate-component](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/format-translate-component)
|
|
34
|
-
- [
|
|
34
|
+
- [best-practice-for-spread-syntax](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-spread-syntax)
|
|
35
35
|
- [no-import-other-domain](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/no-import-other-domain)
|
|
36
36
|
- [prohibit-export-array-type](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/prohibit-export-array-type)
|
|
37
37
|
- [prohibit-file-name](https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/prohibit-file-name)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-smarthr",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.1",
|
|
4
4
|
"author": "SmartHR",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "A sharable ESLint plugin for SmartHR",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"json5": "^2.2.3"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"typescript-eslint": "^8.
|
|
29
|
+
"typescript-eslint": "^8.51.0"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
32
|
"eslint": "^9"
|
|
@@ -37,5 +37,5 @@
|
|
|
37
37
|
"eslintplugin",
|
|
38
38
|
"smarthr"
|
|
39
39
|
],
|
|
40
|
-
"gitHead": "
|
|
40
|
+
"gitHead": "8dd34c6f8ed86887e4287f55b2b511e340291b32"
|
|
41
41
|
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# smarthr/best-practice-for-spread-syntax
|
|
2
|
+
|
|
3
|
+
- 意図しない属性の上書きを防ぐため、spread syntax({ ...b } のようにjs, jsxでオブジェクトを展開する記述)を通常の属性より先に記述するよう促すruleです
|
|
4
|
+
- eslint を `--fix` オプション付きで実行する際、 fix オプション を true にすると自動修正します
|
|
5
|
+
- !!! 要注意 !!! 自動修正は属性の並び替えだけ行うため、spread syntaxによって上書きすることを期待していたロジックが狂う可能性があります
|
|
6
|
+
- jsxのspread attributesのみ、objectのspread sytaxのみチェック対象にしたい場合、checkTypeオプションに only-jsx, only-object を指定してください
|
|
7
|
+
|
|
8
|
+
# spread syntax を通常の属性より後に記述した場合に発生する問題
|
|
9
|
+
|
|
10
|
+
spread syntaxより先に通常の属性を記述した場合、** spread syntaxで値が上書きされる ** 可能性があります。
|
|
11
|
+
|
|
12
|
+
```jsx
|
|
13
|
+
const AnyComponent = (props: Props) => {
|
|
14
|
+
...
|
|
15
|
+
return <Fuga id="ABC" {...props} />
|
|
16
|
+
}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
上記例の場合、** Props型がidを含むか? 含む場合必須か?などの確認 ** が必要になります。
|
|
20
|
+
(idが必須の場合、Fugaにベタ書きしているidがそもそも不要になるため)
|
|
21
|
+
また`idのデフォルト値が"ABC", propsでidが指定された場合そちらを優先` というロジックが必要かどうかを該当コードの部分だけで判断出来ず、広範囲の確認が必要になりがちです。
|
|
22
|
+
特にidなど多用され、HTMLの要素が持つ属性と名前が被っている場合、意図せず上書きされてしまう問題が発生する可能性が高く危険です。
|
|
23
|
+
そのため下記の様に記述することを推奨します。
|
|
24
|
+
|
|
25
|
+
```jsx
|
|
26
|
+
// propsがidを含む可能性がある場合
|
|
27
|
+
const AnyComponent = (props: Props) => {
|
|
28
|
+
...
|
|
29
|
+
return <Fuga {...props} id={props.id || 'ABC'} />
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// propsがidを含む可能性がない場合(もしくはidを固定値にしたい場合)
|
|
33
|
+
const AnyComponent = (props: Props) => {
|
|
34
|
+
...
|
|
35
|
+
return <Fuga {...props} id="ABC" />
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
推奨の記法では
|
|
40
|
+
|
|
41
|
+
- spread syntaxによる意図せぬ上書きを回避できる
|
|
42
|
+
- コードとしてデフォルト値なのか、固定値なのかが一目でわかる
|
|
43
|
+
|
|
44
|
+
などのメリットがあります。
|
|
45
|
+
|
|
46
|
+
例ではjsxを使用しましたが、通常のオブジェクトの場合も同様にチェックします
|
|
47
|
+
|
|
48
|
+
```js
|
|
49
|
+
// NG例
|
|
50
|
+
const obj = {
|
|
51
|
+
fuga: 'piyo',
|
|
52
|
+
...hoge,
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// OK例
|
|
56
|
+
const obj = {
|
|
57
|
+
...hoge,
|
|
58
|
+
fuga: hoge.fuga || 'piyo',
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
## rules
|
|
64
|
+
|
|
65
|
+
```js
|
|
66
|
+
{
|
|
67
|
+
rules: {
|
|
68
|
+
'smarthr/best-practice-for-spread-syntax': [
|
|
69
|
+
'error', // 'warn', 'off'
|
|
70
|
+
{
|
|
71
|
+
fix: false // true
|
|
72
|
+
// 個別に対象指定する場合(default always)
|
|
73
|
+
// checkType: 'always', // only-jsx, only-object
|
|
74
|
+
},
|
|
75
|
+
]
|
|
76
|
+
},
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## ❌ Incorrect
|
|
81
|
+
|
|
82
|
+
```jsx
|
|
83
|
+
<AnyComponent hoge="hoge" {...props} />
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
```jsx
|
|
87
|
+
<AnyComponent {...fuga} hoge="hoge" {...piyo} />
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
```jsx
|
|
91
|
+
const obj = {
|
|
92
|
+
fuga: 'piyo',
|
|
93
|
+
...hoge,
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## ✅ Correct
|
|
98
|
+
|
|
99
|
+
```jsx
|
|
100
|
+
<AnyComponent {...props} hoge="hoge" />
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
```jsx
|
|
104
|
+
<AnyComponent {...props} hoge={props.hoge || "hoge"} />
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
```jsx
|
|
108
|
+
<AnyComponent {...fuga} {...piyo} hoge="hoge" />
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
```jsx
|
|
112
|
+
const obj = {
|
|
113
|
+
...hoge,
|
|
114
|
+
fuga: hoge.fuga || 'piyo',
|
|
115
|
+
}
|
|
116
|
+
```
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
const SCHEMA = [
|
|
2
|
+
{
|
|
3
|
+
type: 'object',
|
|
4
|
+
properties: {
|
|
5
|
+
fix: { type: 'boolean', default: false },
|
|
6
|
+
checkType: { type: 'string', enum: ['always', 'only-jsx', 'only-object'], default: 'always' },
|
|
7
|
+
},
|
|
8
|
+
additionalProperties: false,
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
const CHECK_JSX_REGEX = /^(always|only-jsx)$/
|
|
13
|
+
const CHECK_OBJ_REGEX = /^(always|only-object)$/
|
|
14
|
+
|
|
15
|
+
// HINT: -1: 見つからなかった >= 0: 見つかった
|
|
16
|
+
const getInsertIndex = (node, type, attributesKey) => {
|
|
17
|
+
const attributes = node.parent[attributesKey]
|
|
18
|
+
|
|
19
|
+
// HINT: 関数のspread elementの場合などは除外したいので属性がない場合に対応
|
|
20
|
+
if (attributes) {
|
|
21
|
+
for (let i = 0; i < attributes.length; i++) {
|
|
22
|
+
const a = attributes[i]
|
|
23
|
+
|
|
24
|
+
if (a === node) {
|
|
25
|
+
return -1
|
|
26
|
+
} else if (a.type !== type) {
|
|
27
|
+
return i
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return -1
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
|
|
37
|
+
*/
|
|
38
|
+
module.exports = {
|
|
39
|
+
meta: {
|
|
40
|
+
type: 'problem',
|
|
41
|
+
fixable: 'code',
|
|
42
|
+
schema: SCHEMA,
|
|
43
|
+
},
|
|
44
|
+
create(context) {
|
|
45
|
+
const option = context.options[0] || {}
|
|
46
|
+
const fix = option.fix
|
|
47
|
+
const checkType = option.checkType || 'always'
|
|
48
|
+
|
|
49
|
+
const generateAction = (type, attributesKey, fixAction) => {
|
|
50
|
+
return ((node) => {
|
|
51
|
+
const insertIndex = getInsertIndex(node, type, attributesKey)
|
|
52
|
+
|
|
53
|
+
if (insertIndex !== -1) {
|
|
54
|
+
const code = context.sourceCode.getText(node)
|
|
55
|
+
|
|
56
|
+
context.report({
|
|
57
|
+
node,
|
|
58
|
+
message: `"${code}" は意図しない上書きを防ぐため、spread syntaxでない属性より先に記述してください
|
|
59
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-spread-syntax`,
|
|
60
|
+
fix: fixAction ? (fixer) => {
|
|
61
|
+
const elementNode = node.parent
|
|
62
|
+
const normals = []
|
|
63
|
+
const spreads = []
|
|
64
|
+
|
|
65
|
+
elementNode[attributesKey].forEach((a, i) => {
|
|
66
|
+
if (a !== node) {
|
|
67
|
+
if (insertIndex === i) {
|
|
68
|
+
spreads.push(code)
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
(a.type === type ? spreads : normals).push(context.sourceCode.getText(a))
|
|
72
|
+
}
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
return fixer.replaceText(
|
|
76
|
+
elementNode,
|
|
77
|
+
fixAction(spreads.concat(normals), elementNode),
|
|
78
|
+
)
|
|
79
|
+
} : null
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
})
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
JSXSpreadAttribute: (
|
|
87
|
+
CHECK_JSX_REGEX.test(checkType)
|
|
88
|
+
? generateAction('JSXSpreadAttribute', 'attributes', (option.fix) && ((attributes, e) => `<${e.name.name} ${attributes.join(' ')}${e.selfClosing ? ' /' : ''}>`))
|
|
89
|
+
: undefined
|
|
90
|
+
),
|
|
91
|
+
SpreadElement: (
|
|
92
|
+
CHECK_OBJ_REGEX.test(checkType)
|
|
93
|
+
? generateAction('SpreadElement', 'properties', (option.fix) && ((attributes) => `{ ${attributes.join(', ')} }`))
|
|
94
|
+
: undefined
|
|
95
|
+
),
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
}
|
|
99
|
+
module.exports.schema = SCHEMA
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
const rule = require('../rules/best-practice-for-spread-syntax')
|
|
2
|
+
const RuleTester = require('eslint').RuleTester
|
|
3
|
+
|
|
4
|
+
const ruleTester = new RuleTester({
|
|
5
|
+
languageOptions: {
|
|
6
|
+
parserOptions: {
|
|
7
|
+
ecmaFeatures: {
|
|
8
|
+
jsx: true,
|
|
9
|
+
},
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
const errorMessage = (code) => `"${code}" は意図しない上書きを防ぐため、spread syntaxでない属性より先に記述してください
|
|
15
|
+
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/best-practice-for-spread-syntax`
|
|
16
|
+
|
|
17
|
+
ruleTester.run('best-practice-for-spread-syntax', rule, {
|
|
18
|
+
valid: [
|
|
19
|
+
{ code: `<Fuga {...props} id={props.id || 'ABC'} />` },
|
|
20
|
+
{ code: `<Fuga {...props1} {...props2} id="ABC" />` },
|
|
21
|
+
{ code: `const hoge = { ...props, id: props.id || 'ABC' }` },
|
|
22
|
+
{ code: `const hoge = { ...props1, ...props2, id: 'ABC' }` },
|
|
23
|
+
{ code: `dig(target, ...keys.slice(1))` },
|
|
24
|
+
],
|
|
25
|
+
invalid: [
|
|
26
|
+
{
|
|
27
|
+
code: `<Fuga id={props.id || 'ABC'} {...props} />`,
|
|
28
|
+
options: [ { fix: true } ],
|
|
29
|
+
errors: [ { message: errorMessage('{...props}') } ],
|
|
30
|
+
output: `<Fuga {...props} id={props.id || 'ABC'} />`
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
code: `<Fuga {...props1} id="ABC" {...props2} />`,
|
|
34
|
+
options: [ { fix: true, checkType: 'only-jsx' } ],
|
|
35
|
+
errors: [ { message: errorMessage('{...props2}') } ],
|
|
36
|
+
output: `<Fuga {...props1} {...props2} id="ABC" />`
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
code: `<Fuga id="ABC" {...props1} {...props2} />`,
|
|
40
|
+
options: [ { fix: true, checkType: 'only-jsx' } ],
|
|
41
|
+
errors: [ { message: errorMessage('{...props1}') }, { message: errorMessage('{...props2}') } ],
|
|
42
|
+
output: `<Fuga {...props1} {...props2} id="ABC" />`
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
code: `const hoge = { id: props.id || 'ABC', ...props }`,
|
|
46
|
+
options: [ { fix: true, checkType: 'only-object' } ],
|
|
47
|
+
errors: [ { message: errorMessage('...props') } ],
|
|
48
|
+
output: `const hoge = { ...props, id: props.id || 'ABC' }`
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
code: `const hoge = { ...props1, id: 'ABC', ...props2 }`,
|
|
52
|
+
options: [ { fix: true, checkType: 'only-object' } ],
|
|
53
|
+
errors: [ { message: errorMessage('...props2') } ],
|
|
54
|
+
output: `const hoge = { ...props1, ...props2, id: 'ABC' }`
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
code: `const hoge = { id: 'ABC', ...props1, ...props2 }`,
|
|
58
|
+
options: [ { fix: true, checkType: 'only-object' } ],
|
|
59
|
+
errors: [ { message: errorMessage('...props1') }, { message: errorMessage('...props2') } ],
|
|
60
|
+
output: `const hoge = { ...props1, ...props2, id: 'ABC' }`
|
|
61
|
+
},
|
|
62
|
+
]
|
|
63
|
+
})
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
# smarthr/jsx-start-with-spread-attributes
|
|
2
|
-
|
|
3
|
-
- jsxを記述する際、意図しない属性の上書きを防ぐため、spread-attributesを先に指定するように強制するruleです
|
|
4
|
-
- eslint を `--fix` オプション付きで実行する際、 fix option を true にすると自動修正します
|
|
5
|
-
|
|
6
|
-
## rules
|
|
7
|
-
|
|
8
|
-
```js
|
|
9
|
-
{
|
|
10
|
-
rules: {
|
|
11
|
-
'smarthr/jsx-start-with-spread-attributes': [
|
|
12
|
-
'error', // 'warn', 'off'
|
|
13
|
-
{
|
|
14
|
-
fix: false, // true
|
|
15
|
-
},
|
|
16
|
-
]
|
|
17
|
-
},
|
|
18
|
-
}
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
## ❌ Incorrect
|
|
22
|
-
|
|
23
|
-
```jsx
|
|
24
|
-
<AnyComponent hoge="hoge" {...props} />
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## ✅ Correct
|
|
28
|
-
|
|
29
|
-
```jsx
|
|
30
|
-
<AnyComponent {...props} hoge="hoge" />
|
|
31
|
-
```
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
const SCHEMA = [
|
|
2
|
-
{
|
|
3
|
-
type: 'object',
|
|
4
|
-
properties: {
|
|
5
|
-
fix: { type: 'boolean', default: false },
|
|
6
|
-
},
|
|
7
|
-
additionalProperties: false,
|
|
8
|
-
}
|
|
9
|
-
]
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* @type {import('@typescript-eslint/utils').TSESLint.RuleModule<''>}
|
|
13
|
-
*/
|
|
14
|
-
module.exports = {
|
|
15
|
-
meta: {
|
|
16
|
-
type: 'problem',
|
|
17
|
-
fixable: 'code',
|
|
18
|
-
schema: SCHEMA,
|
|
19
|
-
},
|
|
20
|
-
create(context) {
|
|
21
|
-
return {
|
|
22
|
-
JSXSpreadAttribute: (node) => {
|
|
23
|
-
// HINT: -2: 計算中 -1: 見つからなかった >= 0: 見つかった
|
|
24
|
-
const insertIndex = node.parent.attributes.reduce((h, a, i) => {
|
|
25
|
-
if (h === -2) {
|
|
26
|
-
if (a === node) {
|
|
27
|
-
return -1
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
return a.type !== 'JSXSpreadAttribute' ? i : h
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return h
|
|
34
|
-
}, -2)
|
|
35
|
-
|
|
36
|
-
if (insertIndex >= 0) {
|
|
37
|
-
const option = context.options[0]
|
|
38
|
-
const attributeCode = context.sourceCode.getText(node)
|
|
39
|
-
|
|
40
|
-
context.report({
|
|
41
|
-
node,
|
|
42
|
-
message: `"${attributeCode}" は意図しない上書きを防ぐため、spread attributesでない属性より先に記述してください
|
|
43
|
-
- 詳細: https://github.com/kufu/tamatebako/tree/master/packages/eslint-plugin-smarthr/rules/jsx-start-with-spread-attributes`,
|
|
44
|
-
fix: option?.fix ? (fixer) => {
|
|
45
|
-
const elementNode = node.parent
|
|
46
|
-
const sortedAttributes = [...elementNode.attributes].reduce((p, a, i) => {
|
|
47
|
-
if (insertIndex === i) {
|
|
48
|
-
p = [attributeCode, ...p]
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
if (a !== node) {
|
|
52
|
-
p = [...p, context.sourceCode.getText(a)]
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return p
|
|
56
|
-
}, [])
|
|
57
|
-
|
|
58
|
-
return fixer.replaceText(
|
|
59
|
-
elementNode,
|
|
60
|
-
`<${elementNode.name.name} ${sortedAttributes.join(' ')}${elementNode.selfClosing ? '/' : ''}>`
|
|
61
|
-
)
|
|
62
|
-
} : null
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
},
|
|
66
|
-
};
|
|
67
|
-
},
|
|
68
|
-
}
|
|
69
|
-
module.exports.schema = SCHEMA
|