eslint-plugin-imports-regulation 0.2.2 → 0.2.4
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.
|
@@ -110,9 +110,33 @@ const rule = {
|
|
|
110
110
|
const unmarkedTypeOnly = (node) => node.importKind === 'value'
|
|
111
111
|
&& node.specifiers.length > 0
|
|
112
112
|
&& node.specifiers.every(s => s.type === 'ImportSpecifier' && s.importKind === 'type');
|
|
113
|
+
/**
|
|
114
|
+
* Every binding is only used as a type, whether or not it says so yet.
|
|
115
|
+
*
|
|
116
|
+
* Memoised because `groupOf` asks once per import and the answer walks the scope chain.
|
|
117
|
+
*/
|
|
118
|
+
const inferred = new Map();
|
|
119
|
+
const isInferredTypeOnly = (node) => {
|
|
120
|
+
const cached = inferred.get(node);
|
|
121
|
+
if (cached !== undefined)
|
|
122
|
+
return cached;
|
|
123
|
+
const typeOnly = typeOnlyBindings(node);
|
|
124
|
+
const result = node.specifiers.length > 0
|
|
125
|
+
&& node.specifiers.every(specifier => typeOnly.has(specifier.local.name));
|
|
126
|
+
inferred.set(node, result);
|
|
127
|
+
return result;
|
|
128
|
+
};
|
|
113
129
|
// `isTypeOnly`, not `typeOnly`: the option of that name is a spelling, this is a fact.
|
|
130
|
+
//
|
|
131
|
+
// 🚨 The inferred case has to count here, not just the written one. Classify by syntax alone
|
|
132
|
+
// and an import that is *about* to be marked type-only still sorts as a value import, so the
|
|
133
|
+
// order check fires on a classification that is one fix out of date and swaps two imports
|
|
134
|
+
// that both end up in the same group. Stable sorting then keeps them swapped, so the author
|
|
135
|
+
// loses their order for no reason and the file never settles back.
|
|
114
136
|
const groupOf = (node) => {
|
|
115
|
-
const isTypeOnly = node.importKind === 'type'
|
|
137
|
+
const isTypeOnly = node.importKind === 'type'
|
|
138
|
+
|| unmarkedTypeOnly(node)
|
|
139
|
+
|| (inferTypeOnlyImports && isInferredTypeOnly(node));
|
|
116
140
|
const base = originOf(node.source.value) === 'internal' ? INTERNAL_TYPE : EXTERNAL_TYPE;
|
|
117
141
|
return isTypeOnly ? base : base + 1;
|
|
118
142
|
};
|
|
@@ -173,9 +197,9 @@ const rule = {
|
|
|
173
197
|
const typeOnly = typeOnlyBindings(node);
|
|
174
198
|
if (typeOnly.size === 0)
|
|
175
199
|
return false;
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
if (
|
|
200
|
+
// Not gated on `preferTypeDeclarations`: that option is about leaving a spelling you
|
|
201
|
+
// wrote alone. Here there is no spelling yet, and `import type` is the one to write.
|
|
202
|
+
if (isInferredTypeOnly(node)) {
|
|
179
203
|
const keyword = source.getFirstToken(node);
|
|
180
204
|
if (!keyword)
|
|
181
205
|
return false;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-plugin-imports-regulation",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Order imports:
|
|
3
|
+
"version": "0.2.4",
|
|
4
|
+
"description": "Order imports: external type-only, external, blank line, internal type-only, internal — with type specifiers last inside each import.",
|
|
5
5
|
"author": "Robert Sandiford",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"devDependencies": {
|
|
32
32
|
"@types/node": "^22.19.15",
|
|
33
33
|
"eslint": "^10.8.1",
|
|
34
|
-
"typescript-eslint": "^8.
|
|
34
|
+
"typescript-eslint": "^8.70.0"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
|
37
37
|
"compile": "tsc",
|