@chacki/eslint-plugin-require-extensions 0.0.1 → 0.0.2
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/index.js +42 -15
- package/package.json +1 -1
package/index.js
CHANGED
@@ -8,7 +8,7 @@ module.exports = {
|
|
8
8
|
type: 'problem',
|
9
9
|
docs: {
|
10
10
|
description:
|
11
|
-
|
11
|
+
'Относительные импорты/экспорты должны заканчиваться на .js (или .ts→.js/.tsx→.js)',
|
12
12
|
category: 'ESM',
|
13
13
|
recommended: true,
|
14
14
|
},
|
@@ -38,43 +38,66 @@ module.exports = {
|
|
38
38
|
const extMapping = opts.extMapping || { '.ts': '.js', '.tsx': '.js' };
|
39
39
|
|
40
40
|
function checkNode(node) {
|
41
|
-
const source = node.source
|
42
|
-
if (!source) return;
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
}
|
41
|
+
const source = node.source?.value;
|
42
|
+
if (!source || typeof source !== 'string') return;
|
43
|
+
|
44
|
+
const raw = source.replace(/\?.*$/, '');
|
45
|
+
if (!raw.startsWith('.') || extensions.some((e) => raw.endsWith(e))) return;
|
47
46
|
|
48
47
|
const absPath = resolve(dirname(context.getFilename()), raw);
|
48
|
+
|
49
49
|
for (const ext of extensions) {
|
50
50
|
if (existsSync(absPath + ext)) {
|
51
|
-
// найден .js-файл
|
52
51
|
return context.report({
|
53
52
|
node: node.source,
|
54
|
-
message: 'Relative import/
|
53
|
+
message: 'Relative import/export must end with {{ext}}',
|
55
54
|
data: { ext },
|
56
55
|
fix(fixer) {
|
57
|
-
|
56
|
+
const newPath = `${raw + ext}`;
|
57
|
+
return fixer.replaceTextRange(
|
58
|
+
node.source.range,
|
59
|
+
`'${newPath}'`
|
60
|
+
);
|
58
61
|
},
|
59
62
|
});
|
60
63
|
}
|
61
64
|
}
|
65
|
+
|
62
66
|
for (const [from, to] of Object.entries(extMapping)) {
|
63
67
|
if (raw.endsWith(from)) {
|
64
68
|
const without = raw.slice(0, -from.length);
|
65
69
|
const target = without + to;
|
66
|
-
|
70
|
+
const targetPath = resolve(dirname(context.getFilename()), target);
|
71
|
+
|
72
|
+
if (existsSync(targetPath)) {
|
67
73
|
return context.report({
|
68
74
|
node: node.source,
|
69
75
|
message: 'Change extension from {{from}} to {{to}}',
|
70
76
|
data: { from, to },
|
71
77
|
fix(fixer) {
|
72
|
-
return fixer.
|
78
|
+
return fixer.replaceTextRange(
|
79
|
+
node.source.range,
|
80
|
+
`'${target}'`
|
81
|
+
);
|
73
82
|
},
|
74
83
|
});
|
75
84
|
}
|
76
85
|
}
|
77
86
|
}
|
87
|
+
|
88
|
+
const fallbackExt = extensions[0];
|
89
|
+
return context.report({
|
90
|
+
node: node.source,
|
91
|
+
message: 'Add missing extension {{ext}}',
|
92
|
+
data: { ext: fallbackExt },
|
93
|
+
fix(fixer) {
|
94
|
+
const newPath = `${raw + fallbackExt}`;
|
95
|
+
return fixer.replaceTextRange(
|
96
|
+
node.source.range,
|
97
|
+
`'${newPath}'`
|
98
|
+
);
|
99
|
+
},
|
100
|
+
});
|
78
101
|
}
|
79
102
|
|
80
103
|
return {
|
@@ -98,8 +121,9 @@ module.exports = {
|
|
98
121
|
},
|
99
122
|
create(context) {
|
100
123
|
function checkNode(node) {
|
101
|
-
const source = node.source
|
102
|
-
if (!source) return;
|
124
|
+
const source = node.source?.value;
|
125
|
+
if (!source || typeof source !== 'string') return;
|
126
|
+
|
103
127
|
const raw = source.replace(/\?.*$/, '');
|
104
128
|
if (!raw.startsWith('.')) return;
|
105
129
|
|
@@ -109,7 +133,10 @@ module.exports = {
|
|
109
133
|
node: node.source,
|
110
134
|
message: 'Directory imports must end with /index.js',
|
111
135
|
fix(fixer) {
|
112
|
-
return fixer.
|
136
|
+
return fixer.replaceTextRange(
|
137
|
+
node.source.range,
|
138
|
+
`'${raw}/index.js'`
|
139
|
+
);
|
113
140
|
},
|
114
141
|
});
|
115
142
|
}
|