Skip to content

Commit ba58977

Browse files
committed
feat: add forSubpaths and forSiblings options
1 parent b1dce57 commit ba58977

File tree

2 files changed

+100
-6
lines changed

2 files changed

+100
-6
lines changed

src/rules/prefer-alias.js

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import P from 'path'
66

77
const isParentImport = path => /^(\.\/)?\.\.\//.test(path)
88

9+
const isSiblingImport = path => /^\.\/[^/]+$/.test(path)
10+
11+
const isSubpathImport = path => /^\.\/.+\//.test(path)
12+
913
const findMatchingAlias = (sourcePath, currentFile, options) => {
1014
const resolvePath = options.resolvePath || defaultResolvePath
1115

@@ -61,8 +65,22 @@ export default {
6165
options.alias
6266
|> keys
6367
|> some(alias => sourcePath |> startsWith(`${alias}/`))
64-
// relative parent
65-
if (sourcePath |> isParentImport) {
68+
69+
const importWithoutAlias = resolvePath(sourcePath, currentFile, options)
70+
71+
const [shouldAlias, shouldUnalias] = [
72+
!hasAlias &&
73+
((importWithoutAlias |> isParentImport) ||
74+
((importWithoutAlias |> isSiblingImport) &&
75+
options.forSiblings) ||
76+
((importWithoutAlias |> isSubpathImport) && options.forSubpaths)),
77+
hasAlias &&
78+
(((importWithoutAlias |> isSiblingImport) &&
79+
!options.forSiblings) ||
80+
((importWithoutAlias |> isSubpathImport) &&
81+
!options.forSubpaths)),
82+
]
83+
if (shouldAlias) {
6684
const matchingAlias = findMatchingAlias(
6785
sourcePath,
6886
currentFile,
@@ -78,20 +96,26 @@ export default {
7896
P.relative(matchingAlias.path, absoluteImportPath)
7997
|> replace(/\\/g, '/')
8098
}`
99+
let importType
100+
if (importWithoutAlias |> isSiblingImport) {
101+
importType = 'sibling'
102+
} else if (importWithoutAlias |> isSubpathImport) {
103+
importType = 'subpath'
104+
} else {
105+
importType = 'parent'
106+
}
81107

82108
return context.report({
83109
fix: fixer =>
84110
fixer.replaceTextRange(
85111
[node.source.range[0] + 1, node.source.range[1] - 1],
86112
rewrittenImport,
87113
),
88-
message: `Unexpected parent import '${sourcePath}'. Use '${rewrittenImport}' instead`,
114+
message: `Unexpected ${importType} import '${sourcePath}'. Use '${rewrittenImport}' instead`,
89115
node,
90116
})
91117
}
92-
93-
const importWithoutAlias = resolvePath(sourcePath, currentFile, options)
94-
if (!(importWithoutAlias |> isParentImport) && hasAlias) {
118+
if (shouldUnalias) {
95119
return context.report({
96120
fix: fixer =>
97121
fixer.replaceTextRange(
@@ -116,6 +140,14 @@ export default {
116140
alias: {
117141
type: 'object',
118142
},
143+
forSiblings: {
144+
default: false,
145+
type: 'boolean',
146+
},
147+
forSubpaths: {
148+
default: false,
149+
type: 'boolean',
150+
},
119151
},
120152
type: 'object',
121153
},

src/rules/prefer-alias.spec.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,68 @@ const lint = (code, options = {}) => {
4343

4444
export default tester(
4545
{
46+
'alias for siblings': async () => {
47+
await outputFiles({
48+
'.babelrc.json': JSON.stringify({
49+
plugins: [
50+
[
51+
packageName`babel-plugin-module-resolver`,
52+
{ alias: { '@': '.' } },
53+
],
54+
],
55+
}),
56+
'foo.js': '',
57+
})
58+
expect(
59+
lint("import foo from './foo'", {
60+
eslintConfig: {
61+
rules: {
62+
'self/self': [
63+
'error',
64+
{
65+
forSiblings: true,
66+
},
67+
],
68+
},
69+
},
70+
}),
71+
).toEqual({
72+
messages: ["Unexpected sibling import './foo'. Use '@/foo' instead"],
73+
output: "import foo from '@/foo'",
74+
})
75+
},
76+
'alias for subpaths': async () => {
77+
await outputFiles({
78+
'.babelrc.json': JSON.stringify({
79+
plugins: [
80+
[
81+
packageName`babel-plugin-module-resolver`,
82+
{ alias: { '@': '.' } },
83+
],
84+
],
85+
}),
86+
'sub/foo.js': '',
87+
})
88+
expect(
89+
lint("import foo from './sub/foo'", {
90+
eslintConfig: {
91+
rules: {
92+
'self/self': [
93+
'error',
94+
{
95+
forSubpaths: true,
96+
},
97+
],
98+
},
99+
},
100+
}),
101+
).toEqual({
102+
messages: [
103+
"Unexpected subpath import './sub/foo'. Use '@/sub/foo' instead",
104+
],
105+
output: "import foo from '@/sub/foo'",
106+
})
107+
},
46108
'alias parent': async () => {
47109
await outputFiles({
48110
'.babelrc.json': JSON.stringify({

0 commit comments

Comments
 (0)