eslint-plugin-smarthr 0.1.0 → 0.1.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 +5 -16
- package/README.md +40 -0
- package/package.json +1 -1
- package/rules/require-barrel-import.js +125 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,28 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
### ⚠ BREAKING CHANGES
|
|
9
|
-
|
|
10
|
-
* update prohibit-imoprt option
|
|
5
|
+
### [0.1.1](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.1.0...v0.1.1) (2022-03-08)
|
|
11
6
|
|
|
12
|
-
* chore: require-importの対象ファイル指定方法をoptionの第一階層のkeyにする
|
|
13
7
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
* chore: require-importのdefaultReportMessageを修正
|
|
17
|
-
|
|
18
|
-
* chore: update yarn.lock
|
|
8
|
+
### Features
|
|
19
9
|
|
|
20
|
-
*
|
|
10
|
+
* add require-barrel-import rule ([#13](https://github.com/kufu/eslint-plugin-smarthr/issues/13)) ([79ee88d](https://github.com/kufu/eslint-plugin-smarthr/commit/79ee88d355e01bb8344dc95bd65157e2fbcf916e))
|
|
21
11
|
|
|
22
|
-
|
|
12
|
+
## [0.1.0](https://github.com/kufu/eslint-plugin-smarthr/compare/v0.0.1...v0.1.0) (2022-02-09)
|
|
23
13
|
|
|
24
|
-
* chore: refactoring prohibit-import
|
|
25
14
|
|
|
26
|
-
|
|
15
|
+
### ⚠ BREAKING CHANGES
|
|
27
16
|
|
|
28
17
|
* BREAKING CHANGE: add require-import & update prohibit-import (#12) ([e6c5c44](https://github.com/kufu/eslint-plugin-smarthr/commit/e6c5c445a21620d4b796ded00a685e5da367c7bb)), closes [#12](https://github.com/kufu/eslint-plugin-smarthr/issues/12)
|
|
29
18
|
|
package/README.md
CHANGED
|
@@ -359,6 +359,46 @@ import { SecondaryButton } from 'smarthr-ui'
|
|
|
359
359
|
import useTitle from '.hooks/useTitle'
|
|
360
360
|
```
|
|
361
361
|
|
|
362
|
+
## smarthr/require-barrel-import
|
|
363
|
+
|
|
364
|
+
- tsconfig.json の compilerOptions.pathsに '@/*' としてroot path を指定する必要があります
|
|
365
|
+
- importした対象が本来exportされているべきであるbarrel(index.tsなど)が有る場合、import pathの変更を促します
|
|
366
|
+
- 例: Page/parts/Menu/Item の import は Page/parts/Menu から行わせたい
|
|
367
|
+
- ディレクトリ内のindexファイルを捜査し、対象を決定します
|
|
368
|
+
|
|
369
|
+
### rules
|
|
370
|
+
|
|
371
|
+
```js
|
|
372
|
+
{
|
|
373
|
+
rules: {
|
|
374
|
+
'smarthr/require-barrel-import': 'error',
|
|
375
|
+
},
|
|
376
|
+
}
|
|
377
|
+
```
|
|
378
|
+
|
|
379
|
+
### ❌ Incorrect
|
|
380
|
+
|
|
381
|
+
```js
|
|
382
|
+
// client/src/views/Page/parts/Menu/index.ts
|
|
383
|
+
export { Menu } from './Menu'
|
|
384
|
+
export { Item } from './Item'
|
|
385
|
+
|
|
386
|
+
// client/src/App.tsx
|
|
387
|
+
import { Item } from './Page/parts/Menu/Item'
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
### ✅ Correct
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
```js
|
|
394
|
+
// client/src/views/Page/parts/Menu/index.ts
|
|
395
|
+
export { Menu } from './Menu'
|
|
396
|
+
export { Item } from './Item'
|
|
397
|
+
|
|
398
|
+
// client/src/App.tsx
|
|
399
|
+
import { Item } from './Page/parts/Menu'
|
|
400
|
+
```
|
|
401
|
+
|
|
362
402
|
|
|
363
403
|
## smarthr/redundant-name
|
|
364
404
|
|
package/package.json
CHANGED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
const path = require('path')
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const { replacePaths, rootPath } = require('../libs/common')
|
|
4
|
+
const calculateAbsoluteImportPath = (source) => {
|
|
5
|
+
if (source[0] === '/') {
|
|
6
|
+
return source
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
return Object.entries(replacePaths).reduce((prev, [key, values]) => {
|
|
10
|
+
if (source === prev) {
|
|
11
|
+
return values.reduce((p, v) => {
|
|
12
|
+
if (prev === p) {
|
|
13
|
+
const regexp = new RegExp(`^${key}(.+)$`)
|
|
14
|
+
|
|
15
|
+
if (prev.match(regexp)) {
|
|
16
|
+
return p.replace(regexp, `${path.resolve(`${process.cwd()}/${v}`)}/$1`)
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
return p
|
|
21
|
+
}, prev)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return prev
|
|
25
|
+
}, source)
|
|
26
|
+
}
|
|
27
|
+
const calculateReplacedImportPath = (source) => {
|
|
28
|
+
return Object.entries(replacePaths).reduce((prev, [key, values]) => {
|
|
29
|
+
if (source === prev) {
|
|
30
|
+
return values.reduce((p, v) => {
|
|
31
|
+
if (prev === p) {
|
|
32
|
+
const regexp = new RegExp(`^${path.resolve(`${process.cwd()}/${v}`)}(.+)$`)
|
|
33
|
+
|
|
34
|
+
if (prev.match(regexp)) {
|
|
35
|
+
return p.replace(regexp, `${key}/$1`).replace(/(\/)+/g, '/')
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return p
|
|
40
|
+
}, prev)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return prev
|
|
44
|
+
}, source)
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
module.exports = {
|
|
48
|
+
meta: {
|
|
49
|
+
type: 'suggestion',
|
|
50
|
+
messages: {
|
|
51
|
+
'require-barrel-import': '{{ message }}',
|
|
52
|
+
},
|
|
53
|
+
schema: [],
|
|
54
|
+
},
|
|
55
|
+
create(context) {
|
|
56
|
+
const filename = context.getFilename()
|
|
57
|
+
|
|
58
|
+
// HINT: indexファイルがある == barrelであるとする
|
|
59
|
+
if (filename.match(/\/index\.(js|ts)x?$/)) {
|
|
60
|
+
return {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const dir = (() => {
|
|
64
|
+
const d = filename.split('/')
|
|
65
|
+
d.pop()
|
|
66
|
+
|
|
67
|
+
return d.join('/')
|
|
68
|
+
})()
|
|
69
|
+
|
|
70
|
+
return {
|
|
71
|
+
ImportDeclaration: (node) => {
|
|
72
|
+
let sourceValue = node.source.value
|
|
73
|
+
|
|
74
|
+
if (sourceValue[0] === '.') {
|
|
75
|
+
sourceValue = path.resolve(`${dir}/${sourceValue}`)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
sourceValue = calculateAbsoluteImportPath(sourceValue)
|
|
79
|
+
|
|
80
|
+
if (sourceValue[0] !== '/') {
|
|
81
|
+
return
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const sources = sourceValue.split('/')
|
|
85
|
+
let joinedSources = sourceValue
|
|
86
|
+
let ext = undefined
|
|
87
|
+
|
|
88
|
+
while (sources.length > 0) {
|
|
89
|
+
// HINT: 以下の場合は即終了
|
|
90
|
+
// - import元以下のimportだった場合
|
|
91
|
+
// - rootまで捜索した場合
|
|
92
|
+
if (dir === joinedSources || dir === rootPath) {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
ext = ['ts', 'tsx', 'js', 'jsx'].find((e) => fs.existsSync(`${sources.join('/')}/index.${e}`))
|
|
97
|
+
|
|
98
|
+
if (ext) {
|
|
99
|
+
break
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
sources.pop()
|
|
103
|
+
joinedSources = sources.join('/')
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (
|
|
107
|
+
joinedSources &&
|
|
108
|
+
sourceValue !== joinedSources &&
|
|
109
|
+
!dir.match(new RegExp(`^${joinedSources}/`))
|
|
110
|
+
) {
|
|
111
|
+
const replacedSources = calculateReplacedImportPath(joinedSources)
|
|
112
|
+
|
|
113
|
+
context.report({
|
|
114
|
+
node,
|
|
115
|
+
messageId: 'require-barrel-import',
|
|
116
|
+
data: {
|
|
117
|
+
message: `${replacedSources}からimportするか、${replacedSources}/index.${ext}を削除してください`,
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
}
|
|
125
|
+
module.exports.schema = []
|