@borela-tech/eslint-config 2.1.2 → 2.2.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/README.md +4 -4
- package/bin/build +1 -1
- package/bin/test +1 -1
- package/dist/index.d.mts +5226 -0
- package/dist/index.mjs +872 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +8 -6
- package/src/index.ts +18 -5
- package/src/rules/__tests__/importsAndReExportsAtTop.test.ts +3 -1
- package/src/rules/__tests__/individualImports.test.ts +3 -1
- package/src/rules/__tests__/individualReExports.test.ts +3 -1
- package/src/rules/__tests__/multilineUnionTypes.test.ts +75 -0
- package/src/rules/__tests__/singleLineImports.test.ts +129 -0
- package/src/rules/__tests__/singleLineReExports.test.ts +100 -0
- package/src/rules/__tests__/sortedImports.test.ts +37 -1
- package/src/rules/__tests__/sortedReExports.test.ts +27 -1
- package/src/rules/importsAndReExportsAtTop/CategorizedStatements.ts +2 -2
- package/src/rules/importsAndReExportsAtTop/categorizeStatements.ts +7 -6
- package/src/rules/importsAndReExportsAtTop/generateSortedText.ts +4 -6
- package/src/rules/importsAndReExportsAtTop/getStatementType.ts +1 -1
- package/src/rules/importsAndReExportsAtTop/index.ts +5 -5
- package/src/rules/importsAndReExportsAtTop/isImportDeclaration.ts +7 -0
- package/src/rules/importsAndReExportsAtTop/isReExport.ts +12 -0
- package/src/rules/individualImports.ts +4 -3
- package/src/rules/individualReExports.ts +8 -9
- package/src/rules/multilineUnionTypes/createFix.ts +13 -0
- package/src/rules/multilineUnionTypes/index.ts +52 -0
- package/src/rules/multilineUnionTypes/isMultiline.ts +6 -0
- package/src/rules/singleLineImports/createFix.ts +23 -0
- package/src/rules/singleLineImports/formatAttributes.ts +20 -0
- package/src/rules/singleLineImports/formatNamed.ts +9 -0
- package/src/rules/singleLineImports/formatSpecifiers.ts +32 -0
- package/src/rules/singleLineImports/index.ts +34 -0
- package/src/rules/singleLineImports/isMultiline.ts +6 -0
- package/src/rules/singleLineReExports/createFix.ts +29 -0
- package/src/rules/singleLineReExports/index.ts +48 -0
- package/src/rules/singleLineReExports/isMultiline.ts +6 -0
- package/src/rules/sortedImports/ImportError.ts +4 -1
- package/src/rules/sortedImports/ImportGroup.ts +2 -1
- package/src/rules/sortedImports/ImportGroupOrder.ts +2 -1
- package/src/rules/sortedImports/areSpecifiersSorted.ts +1 -1
- package/src/rules/sortedImports/categorizeImport.ts +4 -0
- package/src/rules/sortedImports/checkAlphabeticalSorting.ts +1 -1
- package/src/rules/sortedImports/createFix/buildSortedCode.ts +2 -1
- package/src/rules/sortedImports/createFix/formatNamedImport.ts +3 -2
- package/src/rules/sortedImports/createFix/getReplacementRange.ts +3 -3
- package/src/rules/sortedImports/createFix/groupImportsByType.ts +1 -0
- package/src/rules/sortedImports/createFix/index.ts +10 -11
- package/src/rules/sortedImports/createFix/sortImportGroups.ts +2 -1
- package/src/rules/sortedImports/getSortKey.ts +8 -2
- package/src/rules/sortedImports/index.ts +8 -5
- package/src/rules/sortedImports/sortSpecifiersText.ts +4 -3
- package/src/rules/sortedReExports/CategorizedReExport.ts +14 -3
- package/src/rules/sortedReExports/ReExportError.ts +5 -2
- package/src/rules/sortedReExports/ReExportGroup.ts +1 -0
- package/src/rules/sortedReExports/ReExportGroupOrder.ts +2 -1
- package/src/rules/sortedReExports/areSpecifiersSorted.ts +1 -1
- package/src/rules/sortedReExports/categorizeReExport.ts +8 -4
- package/src/rules/sortedReExports/categorizeReExports.ts +1 -1
- package/src/rules/sortedReExports/checkAlphabeticalSorting.ts +1 -1
- package/src/rules/sortedReExports/createFix/buildSortedCode.ts +2 -1
- package/src/rules/sortedReExports/createFix/formatNamedReExport.ts +3 -2
- package/src/rules/sortedReExports/createFix/getReplacementRange.ts +1 -1
- package/src/rules/sortedReExports/createFix/groupReExportsByType.ts +1 -0
- package/src/rules/sortedReExports/createFix/index.ts +10 -11
- package/src/rules/sortedReExports/createFix/sortExportGroups.ts +2 -1
- package/src/rules/sortedReExports/getNamedSpecifiers.ts +1 -1
- package/src/rules/sortedReExports/getReExportGroups.ts +1 -1
- package/src/rules/sortedReExports/getSortKey.ts +11 -5
- package/src/rules/sortedReExports/index.ts +8 -5
- package/src/rules/sortedReExports/isNamedReExport.ts +2 -2
- package/src/rules/sortedReExports/sortSpecifiersText.ts +4 -3
- package/tsdown.config.ts +19 -0
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -855
- package/dist/index.js.map +0 -1
- package/src/rules/importsAndReExportsAtTop/ReExport.ts +0 -5
- /package/src/{rules/sortedReExports → lib}/ReExportDeclaration.ts +0 -0
package/dist/index.js
DELETED
|
@@ -1,855 +0,0 @@
|
|
|
1
|
-
// src/index.ts
|
|
2
|
-
import eslint from "@eslint/js";
|
|
3
|
-
import react from "eslint-plugin-react";
|
|
4
|
-
import reactHooks from "eslint-plugin-react-hooks";
|
|
5
|
-
import stylistic from "@stylistic/eslint-plugin";
|
|
6
|
-
import typescript from "typescript-eslint";
|
|
7
|
-
import { defineConfig } from "eslint/config";
|
|
8
|
-
|
|
9
|
-
// src/rules/importsAndReExportsAtTop/getStatementType.ts
|
|
10
|
-
function getStatementType(statement) {
|
|
11
|
-
if (statement.type === "ImportDeclaration")
|
|
12
|
-
return "import";
|
|
13
|
-
if (statement.type === "ExportAllDeclaration")
|
|
14
|
-
return "re-export";
|
|
15
|
-
if (statement.type === "ExportNamedDeclaration") {
|
|
16
|
-
if (statement.source !== null)
|
|
17
|
-
return "re-export";
|
|
18
|
-
}
|
|
19
|
-
return "other";
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// src/rules/importsAndReExportsAtTop/categorizeStatements.ts
|
|
23
|
-
function categorizeStatements(statements) {
|
|
24
|
-
const result = {
|
|
25
|
-
imports: [],
|
|
26
|
-
reExports: [],
|
|
27
|
-
other: []
|
|
28
|
-
};
|
|
29
|
-
for (const statement of statements) {
|
|
30
|
-
const type = getStatementType(statement);
|
|
31
|
-
if (type === "import")
|
|
32
|
-
result.imports.push(statement);
|
|
33
|
-
else if (type === "re-export")
|
|
34
|
-
result.reExports.push(statement);
|
|
35
|
-
else
|
|
36
|
-
result.other.push(statement);
|
|
37
|
-
}
|
|
38
|
-
return result;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// src/rules/importsAndReExportsAtTop/findStatementIndices.ts
|
|
42
|
-
function findStatementIndices(statements) {
|
|
43
|
-
let firstRegularStatement = -1;
|
|
44
|
-
let lastImport = -1;
|
|
45
|
-
let lastReExport = -1;
|
|
46
|
-
for (let i = 0; i < statements.length; i++) {
|
|
47
|
-
const type = getStatementType(statements[i]);
|
|
48
|
-
if (type === "import")
|
|
49
|
-
lastImport = i;
|
|
50
|
-
else if (type === "re-export")
|
|
51
|
-
lastReExport = i;
|
|
52
|
-
else if (type === "other" && firstRegularStatement === -1)
|
|
53
|
-
firstRegularStatement = i;
|
|
54
|
-
}
|
|
55
|
-
return { firstRegularStatement, lastImport, lastReExport };
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
// src/rules/importsAndReExportsAtTop/generateSortedText.ts
|
|
59
|
-
function generateSortedText(context, categories) {
|
|
60
|
-
const allStatements = [
|
|
61
|
-
...categories.imports,
|
|
62
|
-
...categories.reExports,
|
|
63
|
-
...categories.other
|
|
64
|
-
];
|
|
65
|
-
return allStatements.map(
|
|
66
|
-
(node) => context.sourceCode.getText(node)
|
|
67
|
-
).join("\n");
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// src/rules/importsAndReExportsAtTop/hasViolation.ts
|
|
71
|
-
function hasViolation(indices, categories) {
|
|
72
|
-
const { firstRegularStatement, lastImport, lastReExport } = indices;
|
|
73
|
-
if (categories.imports.length === 0 && categories.reExports.length === 0)
|
|
74
|
-
return false;
|
|
75
|
-
const hasImportAfterRegularStatement = categories.imports.length > 0 && firstRegularStatement !== -1 && lastImport > firstRegularStatement;
|
|
76
|
-
const hasReExportAfterRegularStatement = categories.reExports.length > 0 && firstRegularStatement !== -1 && lastReExport > firstRegularStatement;
|
|
77
|
-
return hasImportAfterRegularStatement || hasReExportAfterRegularStatement;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// src/rules/importsAndReExportsAtTop/index.ts
|
|
81
|
-
var importsAndReExportsAtTop = {
|
|
82
|
-
meta: {
|
|
83
|
-
type: "suggestion",
|
|
84
|
-
docs: {
|
|
85
|
-
description: "Enforce imports and re-exports at the top of the file",
|
|
86
|
-
recommended: false
|
|
87
|
-
},
|
|
88
|
-
fixable: "code",
|
|
89
|
-
messages: {
|
|
90
|
-
importsAndReExportsAtTop: "Imports and re-exports should be at the top of the file."
|
|
91
|
-
},
|
|
92
|
-
schema: []
|
|
93
|
-
},
|
|
94
|
-
create(context) {
|
|
95
|
-
return {
|
|
96
|
-
Program(node) {
|
|
97
|
-
const statements = node.body;
|
|
98
|
-
const categories = categorizeStatements(statements);
|
|
99
|
-
const indices = findStatementIndices(statements);
|
|
100
|
-
if (!hasViolation(indices, categories))
|
|
101
|
-
return;
|
|
102
|
-
context.report({
|
|
103
|
-
node,
|
|
104
|
-
messageId: "importsAndReExportsAtTop",
|
|
105
|
-
fix(fixer) {
|
|
106
|
-
const sortedText = generateSortedText(context, categories);
|
|
107
|
-
return fixer.replaceText(node, sortedText);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
// src/rules/individualImports.ts
|
|
116
|
-
var individualImports = {
|
|
117
|
-
meta: {
|
|
118
|
-
docs: {
|
|
119
|
-
description: "Enforce individual imports instead of grouped imports",
|
|
120
|
-
recommended: true
|
|
121
|
-
},
|
|
122
|
-
fixable: "code",
|
|
123
|
-
messages: {
|
|
124
|
-
individualImports: "Use individual imports instead of grouped imports."
|
|
125
|
-
},
|
|
126
|
-
schema: [],
|
|
127
|
-
type: "suggestion"
|
|
128
|
-
},
|
|
129
|
-
create(context) {
|
|
130
|
-
return {
|
|
131
|
-
ImportDeclaration(node) {
|
|
132
|
-
if (node.specifiers.length <= 1)
|
|
133
|
-
return;
|
|
134
|
-
context.report({
|
|
135
|
-
node,
|
|
136
|
-
messageId: "individualImports",
|
|
137
|
-
fix(fixer) {
|
|
138
|
-
const source = node.source.raw;
|
|
139
|
-
const specifiers = node.specifiers.filter((s) => s.type === "ImportSpecifier").map((s) => `import {${s.local.name}} from ${source}`).join("\n");
|
|
140
|
-
return fixer.replaceText(node, specifiers);
|
|
141
|
-
}
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
// src/rules/individualReExports.ts
|
|
149
|
-
var individualReExports = {
|
|
150
|
-
meta: {
|
|
151
|
-
docs: {
|
|
152
|
-
description: "Enforce individual exports instead of grouped exports",
|
|
153
|
-
recommended: true
|
|
154
|
-
},
|
|
155
|
-
fixable: "code",
|
|
156
|
-
messages: {
|
|
157
|
-
individualReExports: "Use individual exports instead of grouped exports."
|
|
158
|
-
},
|
|
159
|
-
schema: [],
|
|
160
|
-
type: "suggestion"
|
|
161
|
-
},
|
|
162
|
-
create(context) {
|
|
163
|
-
return {
|
|
164
|
-
ExportNamedDeclaration(node) {
|
|
165
|
-
const exportNode = node;
|
|
166
|
-
if (!exportNode.source || exportNode.specifiers.length <= 1)
|
|
167
|
-
return;
|
|
168
|
-
context.report({
|
|
169
|
-
node,
|
|
170
|
-
messageId: "individualReExports",
|
|
171
|
-
fix(fixer) {
|
|
172
|
-
const source = exportNode.source.value;
|
|
173
|
-
const typeKeyword = exportNode.exportKind === "type" ? "type " : "";
|
|
174
|
-
const specifiers = exportNode.specifiers.map((s) => {
|
|
175
|
-
const localName = s.local.type === "Identifier" ? s.local.name : s.local.value;
|
|
176
|
-
const exportedName = s.exported.type === "Identifier" ? s.exported.name : s.exported.value;
|
|
177
|
-
const name = localName === exportedName ? localName : `${localName} as ${exportedName}`;
|
|
178
|
-
return `export ${typeKeyword}{${name}} from '${source}'`;
|
|
179
|
-
}).join("\n");
|
|
180
|
-
return fixer.replaceText(node, specifiers);
|
|
181
|
-
}
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
// src/rules/sortedImports/categorizeImport.ts
|
|
189
|
-
function categorizeImport(declaration) {
|
|
190
|
-
if (declaration.importKind === "type")
|
|
191
|
-
return "type";
|
|
192
|
-
if (declaration.specifiers.length === 0)
|
|
193
|
-
return "side-effect";
|
|
194
|
-
if (declaration.specifiers.some((s) => s.type === "ImportDefaultSpecifier"))
|
|
195
|
-
return "default";
|
|
196
|
-
return "named";
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// src/rules/sortedImports/getSortKey.ts
|
|
200
|
-
function getSortKey(declaration) {
|
|
201
|
-
const group = categorizeImport(declaration);
|
|
202
|
-
if (group === "side-effect")
|
|
203
|
-
return declaration.source.value;
|
|
204
|
-
if (group === "default") {
|
|
205
|
-
const defaultSpecifier = declaration.specifiers.find(
|
|
206
|
-
(s) => s.type === "ImportDefaultSpecifier"
|
|
207
|
-
);
|
|
208
|
-
return defaultSpecifier?.local.name ?? "";
|
|
209
|
-
}
|
|
210
|
-
const specifier = declaration.specifiers[0];
|
|
211
|
-
return specifier.local.name;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// src/rules/sortedImports/categorizeImports.ts
|
|
215
|
-
function categorizeImports(declarations) {
|
|
216
|
-
return declarations.map((declaration) => ({
|
|
217
|
-
declaration,
|
|
218
|
-
group: categorizeImport(declaration),
|
|
219
|
-
sortKey: getSortKey(declaration)
|
|
220
|
-
}));
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
// src/lib/compare.ts
|
|
224
|
-
function compare(a, b) {
|
|
225
|
-
return a.localeCompare(b, "en", { sensitivity: "case" });
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
// src/rules/sortedImports/ImportGroupOrder.ts
|
|
229
|
-
var importGroupOrder = [
|
|
230
|
-
"side-effect",
|
|
231
|
-
"default",
|
|
232
|
-
"named",
|
|
233
|
-
"type"
|
|
234
|
-
];
|
|
235
|
-
|
|
236
|
-
// src/rules/sortedImports/checkAlphabeticalSorting.ts
|
|
237
|
-
function checkAlphabeticalSorting(categorized) {
|
|
238
|
-
const errors = [];
|
|
239
|
-
for (const group of importGroupOrder) {
|
|
240
|
-
const groupImports = categorized.filter((c) => c.group === group);
|
|
241
|
-
const sorted = [...groupImports].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
242
|
-
for (let i = 0; i < groupImports.length; i++) {
|
|
243
|
-
if (groupImports[i] !== sorted[i]) {
|
|
244
|
-
errors.push({
|
|
245
|
-
node: groupImports[i].declaration,
|
|
246
|
-
messageId: "sortedImports"
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
return errors;
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// src/rules/sortedImports/checkGroupOrdering.ts
|
|
255
|
-
function checkGroupOrdering(categorized) {
|
|
256
|
-
const errors = [];
|
|
257
|
-
let currentGroupIndex = -1;
|
|
258
|
-
for (const { declaration, group } of categorized) {
|
|
259
|
-
const groupIndex = importGroupOrder.indexOf(group);
|
|
260
|
-
if (groupIndex < currentGroupIndex) {
|
|
261
|
-
errors.push({
|
|
262
|
-
node: declaration,
|
|
263
|
-
messageId: "wrongGroup"
|
|
264
|
-
});
|
|
265
|
-
} else
|
|
266
|
-
currentGroupIndex = groupIndex;
|
|
267
|
-
}
|
|
268
|
-
return errors;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// src/rules/sortedImports/getSpecifierName.ts
|
|
272
|
-
function getSpecifierName(specifier) {
|
|
273
|
-
return specifier.imported.type === "Identifier" ? specifier.imported.name : String(specifier.imported.value);
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// src/rules/sortedImports/areSpecifiersSorted.ts
|
|
277
|
-
function areSpecifiersSorted(specifiers) {
|
|
278
|
-
const names = specifiers.map((s) => getSpecifierName(s));
|
|
279
|
-
const sorted = [...names].sort((a, b) => compare(a, b));
|
|
280
|
-
return names.every((name, i) => name === sorted[i]);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
// src/rules/sortedImports/getNamedSpecifiers.ts
|
|
284
|
-
function getNamedSpecifiers(declaration) {
|
|
285
|
-
return declaration.specifiers.filter(
|
|
286
|
-
(s) => s.type === "ImportSpecifier"
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
// src/rules/sortedImports/checkSpecifiersSorting.ts
|
|
291
|
-
function checkSpecifiersSorting(categorized) {
|
|
292
|
-
const errors = [];
|
|
293
|
-
const namedImports = categorized.filter((c) => c.group === "named");
|
|
294
|
-
for (const { declaration } of namedImports) {
|
|
295
|
-
const specifiers = getNamedSpecifiers(declaration);
|
|
296
|
-
if (specifiers.length > 1 && !areSpecifiersSorted(specifiers)) {
|
|
297
|
-
errors.push({
|
|
298
|
-
node: declaration,
|
|
299
|
-
messageId: "sortedNames"
|
|
300
|
-
});
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
return errors;
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
// src/rules/sortedImports/sortSpecifiersText.ts
|
|
307
|
-
function sortSpecifiersText(specifiers, sourceCode) {
|
|
308
|
-
const sorted = [...specifiers].sort((a, b) => {
|
|
309
|
-
const nameA = getSpecifierName(a);
|
|
310
|
-
const nameB = getSpecifierName(b);
|
|
311
|
-
return compare(nameA, nameB);
|
|
312
|
-
});
|
|
313
|
-
return sorted.map((s) => sourceCode.getText(s)).join(", ");
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
// src/rules/sortedImports/createFix/formatNamedImport.ts
|
|
317
|
-
function formatNamedImport(declaration, sourceCode) {
|
|
318
|
-
const specifiers = getNamedSpecifiers(declaration);
|
|
319
|
-
if (specifiers.length > 1 && !areSpecifiersSorted(specifiers)) {
|
|
320
|
-
const sortedSpecifiers = sortSpecifiersText(specifiers, sourceCode);
|
|
321
|
-
const source = declaration.source.value;
|
|
322
|
-
const prefix = declaration.importKind === "type" ? "import type " : "import ";
|
|
323
|
-
return `${prefix}{${sortedSpecifiers}} from '${source}'`;
|
|
324
|
-
}
|
|
325
|
-
return sourceCode.getText(declaration);
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
// src/rules/sortedImports/createFix/buildSortedCode.ts
|
|
329
|
-
function buildSortedCode(grouped, sourceCode) {
|
|
330
|
-
const sortedCode = [];
|
|
331
|
-
for (const group of importGroupOrder) {
|
|
332
|
-
for (const { declaration } of grouped[group]) {
|
|
333
|
-
if (group === "named" || group === "type")
|
|
334
|
-
sortedCode.push(formatNamedImport(declaration, sourceCode));
|
|
335
|
-
else
|
|
336
|
-
sortedCode.push(sourceCode.getText(declaration));
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
return sortedCode;
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
// src/rules/sortedImports/createFix/groupImportsByType.ts
|
|
343
|
-
function groupImportsByType(categorized) {
|
|
344
|
-
const grouped = {
|
|
345
|
-
"side-effect": [],
|
|
346
|
-
default: [],
|
|
347
|
-
named: [],
|
|
348
|
-
type: []
|
|
349
|
-
};
|
|
350
|
-
for (const item of categorized)
|
|
351
|
-
grouped[item.group].push(item);
|
|
352
|
-
return grouped;
|
|
353
|
-
}
|
|
354
|
-
|
|
355
|
-
// src/rules/sortedImports/createFix/sortImportGroups.ts
|
|
356
|
-
function sortImportGroups(grouped) {
|
|
357
|
-
grouped["side-effect"].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
358
|
-
grouped["default"].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
359
|
-
grouped["named"].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
360
|
-
grouped["type"].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
// src/rules/sortedImports/createFix/index.ts
|
|
364
|
-
function createFixForGroup(fixer, importDeclarations, sourceCode) {
|
|
365
|
-
if (importDeclarations.length === 0) {
|
|
366
|
-
return null;
|
|
367
|
-
}
|
|
368
|
-
const categorized = categorizeImports(importDeclarations);
|
|
369
|
-
const grouped = groupImportsByType(categorized);
|
|
370
|
-
sortImportGroups(grouped);
|
|
371
|
-
const sortedCode = buildSortedCode(grouped, sourceCode).join("\n");
|
|
372
|
-
const firstImport = importDeclarations[0];
|
|
373
|
-
const lastImport = importDeclarations[importDeclarations.length - 1];
|
|
374
|
-
return fixer.replaceTextRange(
|
|
375
|
-
[firstImport.range[0], lastImport.range[1]],
|
|
376
|
-
sortedCode
|
|
377
|
-
);
|
|
378
|
-
}
|
|
379
|
-
function createFix(fixer, importGroups, sourceCode) {
|
|
380
|
-
const fixes = [];
|
|
381
|
-
for (const group of importGroups) {
|
|
382
|
-
const fix = createFixForGroup(fixer, group, sourceCode);
|
|
383
|
-
if (fix)
|
|
384
|
-
fixes.push(fix);
|
|
385
|
-
}
|
|
386
|
-
return fixes;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// src/rules/sortedImports/getImportGroups.ts
|
|
390
|
-
function getImportGroups(programBody) {
|
|
391
|
-
const groups = [];
|
|
392
|
-
let currentGroup = [];
|
|
393
|
-
for (const statement of programBody) {
|
|
394
|
-
if (statement.type === "ImportDeclaration") {
|
|
395
|
-
currentGroup.push(statement);
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
if (currentGroup.length > 0) {
|
|
399
|
-
groups.push(currentGroup);
|
|
400
|
-
currentGroup = [];
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
if (currentGroup.length > 0)
|
|
404
|
-
groups.push(currentGroup);
|
|
405
|
-
return groups;
|
|
406
|
-
}
|
|
407
|
-
|
|
408
|
-
// src/rules/sortedImports/index.ts
|
|
409
|
-
var sortedImports = {
|
|
410
|
-
meta: {
|
|
411
|
-
docs: {
|
|
412
|
-
description: "Enforce sorted imports alphabetically",
|
|
413
|
-
recommended: true
|
|
414
|
-
},
|
|
415
|
-
fixable: "code",
|
|
416
|
-
messages: {
|
|
417
|
-
sortedImports: "Imports should be sorted alphabetically",
|
|
418
|
-
sortedNames: "Named imports should be sorted alphabetically",
|
|
419
|
-
wrongGroup: "Import is in wrong group"
|
|
420
|
-
},
|
|
421
|
-
schema: [],
|
|
422
|
-
type: "suggestion"
|
|
423
|
-
},
|
|
424
|
-
create(context) {
|
|
425
|
-
return {
|
|
426
|
-
Program(node) {
|
|
427
|
-
const body = node.body;
|
|
428
|
-
const importGroups = getImportGroups(body);
|
|
429
|
-
if (importGroups.length === 0)
|
|
430
|
-
return;
|
|
431
|
-
const allErrors = [];
|
|
432
|
-
for (const group of importGroups) {
|
|
433
|
-
const categorized = categorizeImports(group);
|
|
434
|
-
const errors = [
|
|
435
|
-
...checkGroupOrdering(categorized),
|
|
436
|
-
...checkAlphabeticalSorting(categorized),
|
|
437
|
-
...checkSpecifiersSorting(categorized)
|
|
438
|
-
];
|
|
439
|
-
allErrors.push(...errors);
|
|
440
|
-
}
|
|
441
|
-
for (const error of allErrors) {
|
|
442
|
-
context.report({
|
|
443
|
-
node: error.node,
|
|
444
|
-
messageId: error.messageId,
|
|
445
|
-
fix(fixer) {
|
|
446
|
-
const sourceCode = context.sourceCode;
|
|
447
|
-
return createFix(fixer, importGroups, sourceCode);
|
|
448
|
-
}
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
};
|
|
453
|
-
}
|
|
454
|
-
};
|
|
455
|
-
|
|
456
|
-
// src/rules/sortedReExports/categorizeReExport.ts
|
|
457
|
-
function categorizeReExport(declaration) {
|
|
458
|
-
if (declaration.type === "ExportAllDeclaration")
|
|
459
|
-
return "re-export-all";
|
|
460
|
-
if (declaration.exportKind === "type")
|
|
461
|
-
return "re-export-type";
|
|
462
|
-
return "re-export-named";
|
|
463
|
-
}
|
|
464
|
-
|
|
465
|
-
// src/rules/sortedReExports/getSortKey.ts
|
|
466
|
-
function getSortKey2(declaration) {
|
|
467
|
-
if (declaration.type === "ExportAllDeclaration")
|
|
468
|
-
return declaration.source.value;
|
|
469
|
-
const specifier = declaration.specifiers[0];
|
|
470
|
-
if (!specifier)
|
|
471
|
-
return "";
|
|
472
|
-
return specifier.local.type === "Identifier" ? specifier.local.name : specifier.local.value;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// src/rules/sortedReExports/categorizeReExports.ts
|
|
476
|
-
function categorizeReExports(declarations) {
|
|
477
|
-
return declarations.map((declaration) => {
|
|
478
|
-
return {
|
|
479
|
-
declaration,
|
|
480
|
-
group: categorizeReExport(declaration),
|
|
481
|
-
sortKey: getSortKey2(declaration)
|
|
482
|
-
};
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
// src/rules/sortedReExports/ReExportGroupOrder.ts
|
|
487
|
-
var reExportGroupOrder = [
|
|
488
|
-
"re-export-all",
|
|
489
|
-
"re-export-named",
|
|
490
|
-
"re-export-type"
|
|
491
|
-
];
|
|
492
|
-
|
|
493
|
-
// src/rules/sortedReExports/checkAlphabeticalSorting.ts
|
|
494
|
-
function checkAlphabeticalSorting2(categorized) {
|
|
495
|
-
const errors = [];
|
|
496
|
-
for (const group of reExportGroupOrder) {
|
|
497
|
-
const groupReExports = categorized.filter((c) => c.group === group);
|
|
498
|
-
const sorted = [...groupReExports].sort(
|
|
499
|
-
(a, b) => compare(a.sortKey, b.sortKey)
|
|
500
|
-
);
|
|
501
|
-
for (let i = 0; i < groupReExports.length; i++) {
|
|
502
|
-
if (groupReExports[i] !== sorted[i]) {
|
|
503
|
-
errors.push({
|
|
504
|
-
node: groupReExports[i].declaration,
|
|
505
|
-
messageId: "sortedReExports"
|
|
506
|
-
});
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
}
|
|
510
|
-
return errors;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// src/rules/sortedReExports/checkGroupOrdering.ts
|
|
514
|
-
function checkGroupOrdering2(categorized) {
|
|
515
|
-
const errors = [];
|
|
516
|
-
let currentGroupIndex = -1;
|
|
517
|
-
for (const { declaration, group } of categorized) {
|
|
518
|
-
const groupIndex = reExportGroupOrder.indexOf(group);
|
|
519
|
-
if (groupIndex < currentGroupIndex) {
|
|
520
|
-
errors.push({
|
|
521
|
-
node: declaration,
|
|
522
|
-
messageId: "wrongGroup"
|
|
523
|
-
});
|
|
524
|
-
} else
|
|
525
|
-
currentGroupIndex = groupIndex;
|
|
526
|
-
}
|
|
527
|
-
return errors;
|
|
528
|
-
}
|
|
529
|
-
|
|
530
|
-
// src/rules/sortedReExports/getSpecifierName.ts
|
|
531
|
-
function getSpecifierName2(specifier) {
|
|
532
|
-
return specifier.local.type === "Identifier" ? specifier.local.name : String(specifier.local.value);
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
// src/rules/sortedReExports/areSpecifiersSorted.ts
|
|
536
|
-
function areSpecifiersSorted2(specifiers) {
|
|
537
|
-
const names = specifiers.map((s) => getSpecifierName2(s));
|
|
538
|
-
const sorted = [...names].sort((a, b) => compare(a, b));
|
|
539
|
-
return names.every((name, i) => name === sorted[i]);
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
// src/rules/sortedReExports/getNamedSpecifiers.ts
|
|
543
|
-
function getNamedSpecifiers2(declaration) {
|
|
544
|
-
return declaration.specifiers.filter(
|
|
545
|
-
(s) => s.type === "ExportSpecifier" && s.local.type === "Identifier"
|
|
546
|
-
);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
// src/rules/sortedReExports/isNamedReExport.ts
|
|
550
|
-
function isNamedReExport(x) {
|
|
551
|
-
return x.group !== "re-export-all";
|
|
552
|
-
}
|
|
553
|
-
|
|
554
|
-
// src/rules/sortedReExports/checkSpecifiersSorting.ts
|
|
555
|
-
function checkSpecifiersSorting2(categorized) {
|
|
556
|
-
const errors = [];
|
|
557
|
-
const namedReExports = categorized.filter(isNamedReExport);
|
|
558
|
-
for (const { declaration } of namedReExports) {
|
|
559
|
-
const specifiers = getNamedSpecifiers2(declaration);
|
|
560
|
-
const isSorted = areSpecifiersSorted2(specifiers);
|
|
561
|
-
if (specifiers.length > 1 && !isSorted) {
|
|
562
|
-
errors.push({
|
|
563
|
-
node: declaration,
|
|
564
|
-
messageId: "sortedNames"
|
|
565
|
-
});
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
return errors;
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
// src/rules/sortedReExports/sortSpecifiersText.ts
|
|
572
|
-
function sortSpecifiersText2(specifiers, sourceCode) {
|
|
573
|
-
const sorted = [...specifiers].sort((a, b) => {
|
|
574
|
-
const nameA = getSpecifierName2(a);
|
|
575
|
-
const nameB = getSpecifierName2(b);
|
|
576
|
-
return compare(nameA, nameB);
|
|
577
|
-
});
|
|
578
|
-
return sorted.map((s) => sourceCode.getText(s)).join(", ");
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// src/rules/sortedReExports/createFix/formatNamedReExport.ts
|
|
582
|
-
function formatNamedReExport(declaration, sourceCode) {
|
|
583
|
-
const specifiers = getNamedSpecifiers2(declaration);
|
|
584
|
-
if (specifiers.length > 1 && !areSpecifiersSorted2(specifiers)) {
|
|
585
|
-
const sortedSpecifiers = sortSpecifiersText2(specifiers, sourceCode);
|
|
586
|
-
const source = declaration.source.value;
|
|
587
|
-
const prefix = declaration.exportKind === "type" ? "export type " : "export ";
|
|
588
|
-
return `${prefix}{${sortedSpecifiers}} from '${source}'`;
|
|
589
|
-
}
|
|
590
|
-
return sourceCode.getText(declaration);
|
|
591
|
-
}
|
|
592
|
-
|
|
593
|
-
// src/rules/sortedReExports/createFix/buildSortedCode.ts
|
|
594
|
-
function buildSortedCode2(grouped, sourceCode) {
|
|
595
|
-
const sortedCode = [];
|
|
596
|
-
for (const group of reExportGroupOrder) {
|
|
597
|
-
for (const item of grouped[group]) {
|
|
598
|
-
if (isNamedReExport(item)) {
|
|
599
|
-
sortedCode.push(
|
|
600
|
-
formatNamedReExport(
|
|
601
|
-
item.declaration,
|
|
602
|
-
sourceCode
|
|
603
|
-
)
|
|
604
|
-
);
|
|
605
|
-
} else
|
|
606
|
-
sortedCode.push(sourceCode.getText(item.declaration));
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
|
-
return sortedCode;
|
|
610
|
-
}
|
|
611
|
-
|
|
612
|
-
// src/rules/sortedReExports/createFix/groupReExportsByType.ts
|
|
613
|
-
function groupReExportsByType(categorized) {
|
|
614
|
-
const grouped = {
|
|
615
|
-
"re-export-all": [],
|
|
616
|
-
"re-export-named": [],
|
|
617
|
-
"re-export-type": []
|
|
618
|
-
};
|
|
619
|
-
for (const item of categorized)
|
|
620
|
-
grouped[item.group].push(item);
|
|
621
|
-
return grouped;
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// src/rules/sortedReExports/createFix/sortExportGroups.ts
|
|
625
|
-
function sortExportGroups(grouped) {
|
|
626
|
-
grouped["re-export-all"].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
627
|
-
grouped["re-export-named"].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
628
|
-
grouped["re-export-type"].sort((a, b) => compare(a.sortKey, b.sortKey));
|
|
629
|
-
}
|
|
630
|
-
|
|
631
|
-
// src/rules/sortedReExports/createFix/index.ts
|
|
632
|
-
function createFixForGroup2(fixer, reExportDeclarations, sourceCode) {
|
|
633
|
-
if (reExportDeclarations.length === 0) {
|
|
634
|
-
return null;
|
|
635
|
-
}
|
|
636
|
-
const categorized = categorizeReExports(reExportDeclarations);
|
|
637
|
-
const grouped = groupReExportsByType(categorized);
|
|
638
|
-
sortExportGroups(grouped);
|
|
639
|
-
const sortedCode = buildSortedCode2(grouped, sourceCode).join("\n");
|
|
640
|
-
const firstReExport = reExportDeclarations[0];
|
|
641
|
-
const lastReExport = reExportDeclarations[reExportDeclarations.length - 1];
|
|
642
|
-
return fixer.replaceTextRange(
|
|
643
|
-
[firstReExport.range[0], lastReExport.range[1]],
|
|
644
|
-
sortedCode
|
|
645
|
-
);
|
|
646
|
-
}
|
|
647
|
-
function createFix2(fixer, reExportGroups, sourceCode) {
|
|
648
|
-
const fixes = [];
|
|
649
|
-
for (const group of reExportGroups) {
|
|
650
|
-
const fix = createFixForGroup2(fixer, group, sourceCode);
|
|
651
|
-
if (fix)
|
|
652
|
-
fixes.push(fix);
|
|
653
|
-
}
|
|
654
|
-
return fixes;
|
|
655
|
-
}
|
|
656
|
-
|
|
657
|
-
// src/rules/sortedReExports/getReExportGroups.ts
|
|
658
|
-
function isReExportDeclaration(statement) {
|
|
659
|
-
return statement.type === "ExportNamedDeclaration" && statement.source !== null || statement.type === "ExportAllDeclaration";
|
|
660
|
-
}
|
|
661
|
-
function getReExportGroups(programBody) {
|
|
662
|
-
const groups = [];
|
|
663
|
-
let currentGroup = [];
|
|
664
|
-
for (const statement of programBody) {
|
|
665
|
-
if (isReExportDeclaration(statement)) {
|
|
666
|
-
currentGroup.push(statement);
|
|
667
|
-
continue;
|
|
668
|
-
}
|
|
669
|
-
if (currentGroup.length > 0) {
|
|
670
|
-
groups.push(currentGroup);
|
|
671
|
-
currentGroup = [];
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
if (currentGroup.length > 0)
|
|
675
|
-
groups.push(currentGroup);
|
|
676
|
-
return groups;
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
// src/rules/sortedReExports/index.ts
|
|
680
|
-
var sortedReExports = {
|
|
681
|
-
meta: {
|
|
682
|
-
docs: {
|
|
683
|
-
description: "Enforce sorted exports alphabetically",
|
|
684
|
-
recommended: true
|
|
685
|
-
},
|
|
686
|
-
fixable: "code",
|
|
687
|
-
messages: {
|
|
688
|
-
sortedReExports: "Exports should be sorted alphabetically",
|
|
689
|
-
sortedNames: "Named exports should be sorted alphabetically",
|
|
690
|
-
wrongGroup: "Export is in wrong group"
|
|
691
|
-
},
|
|
692
|
-
schema: [],
|
|
693
|
-
type: "suggestion"
|
|
694
|
-
},
|
|
695
|
-
create(context) {
|
|
696
|
-
return {
|
|
697
|
-
Program(node) {
|
|
698
|
-
const body = node.body;
|
|
699
|
-
const reExportGroups = getReExportGroups(body);
|
|
700
|
-
if (reExportGroups.length === 0)
|
|
701
|
-
return;
|
|
702
|
-
const allErrors = [];
|
|
703
|
-
for (const group of reExportGroups) {
|
|
704
|
-
const categorized = categorizeReExports(group);
|
|
705
|
-
const errors = [
|
|
706
|
-
...checkGroupOrdering2(categorized),
|
|
707
|
-
...checkAlphabeticalSorting2(categorized),
|
|
708
|
-
...checkSpecifiersSorting2(categorized)
|
|
709
|
-
];
|
|
710
|
-
allErrors.push(...errors);
|
|
711
|
-
}
|
|
712
|
-
for (const error of allErrors) {
|
|
713
|
-
context.report({
|
|
714
|
-
node: error.node,
|
|
715
|
-
messageId: error.messageId,
|
|
716
|
-
fix(fixer) {
|
|
717
|
-
const sourceCode = context.sourceCode;
|
|
718
|
-
return createFix2(fixer, reExportGroups, sourceCode);
|
|
719
|
-
}
|
|
720
|
-
});
|
|
721
|
-
}
|
|
722
|
-
}
|
|
723
|
-
};
|
|
724
|
-
}
|
|
725
|
-
};
|
|
726
|
-
|
|
727
|
-
// src/index.ts
|
|
728
|
-
var CONFIG = defineConfig([
|
|
729
|
-
{
|
|
730
|
-
ignores: [
|
|
731
|
-
"src/graphql/sdk.ts",
|
|
732
|
-
"**/node_modules/**",
|
|
733
|
-
"**/dist/**"
|
|
734
|
-
]
|
|
735
|
-
},
|
|
736
|
-
{
|
|
737
|
-
settings: {
|
|
738
|
-
react: {
|
|
739
|
-
version: "19"
|
|
740
|
-
}
|
|
741
|
-
}
|
|
742
|
-
},
|
|
743
|
-
eslint.configs.recommended,
|
|
744
|
-
react.configs.flat.recommended,
|
|
745
|
-
stylistic.configs.recommended,
|
|
746
|
-
typescript.configs.recommended,
|
|
747
|
-
typescript.configs.stylistic,
|
|
748
|
-
{
|
|
749
|
-
plugins: {
|
|
750
|
-
"react-hooks": reactHooks
|
|
751
|
-
},
|
|
752
|
-
rules: reactHooks.configs.recommended.rules
|
|
753
|
-
},
|
|
754
|
-
{
|
|
755
|
-
plugins: {
|
|
756
|
-
"@borela-tech": {
|
|
757
|
-
rules: {
|
|
758
|
-
"imports-and-re-exports-at-top": importsAndReExportsAtTop,
|
|
759
|
-
"individual-imports": individualImports,
|
|
760
|
-
"individual-re-exports": individualReExports,
|
|
761
|
-
"sorted-imports": sortedImports,
|
|
762
|
-
"sorted-re-exports": sortedReExports
|
|
763
|
-
}
|
|
764
|
-
}
|
|
765
|
-
},
|
|
766
|
-
rules: {
|
|
767
|
-
"@borela-tech/imports-and-re-exports-at-top": "error",
|
|
768
|
-
"@borela-tech/individual-imports": "error",
|
|
769
|
-
"@borela-tech/individual-re-exports": "error",
|
|
770
|
-
"@borela-tech/sorted-imports": "error",
|
|
771
|
-
"@borela-tech/sorted-re-exports": "error"
|
|
772
|
-
}
|
|
773
|
-
},
|
|
774
|
-
{
|
|
775
|
-
rules: {
|
|
776
|
-
"capitalized-comments": [
|
|
777
|
-
"error",
|
|
778
|
-
"always",
|
|
779
|
-
{ ignoreConsecutiveComments: true }
|
|
780
|
-
],
|
|
781
|
-
"react/react-in-jsx-scope": "off",
|
|
782
|
-
"@stylistic/arrow-parens": [
|
|
783
|
-
"error",
|
|
784
|
-
"as-needed"
|
|
785
|
-
],
|
|
786
|
-
"@stylistic/array-bracket-newline": [
|
|
787
|
-
"error",
|
|
788
|
-
"consistent"
|
|
789
|
-
],
|
|
790
|
-
"@stylistic/array-bracket-spacing": [
|
|
791
|
-
"error",
|
|
792
|
-
"never"
|
|
793
|
-
],
|
|
794
|
-
"@stylistic/array-element-newline": [
|
|
795
|
-
"error",
|
|
796
|
-
"consistent"
|
|
797
|
-
],
|
|
798
|
-
"@stylistic/block-spacing": "off",
|
|
799
|
-
"@stylistic/brace-style": [
|
|
800
|
-
"error",
|
|
801
|
-
"1tbs",
|
|
802
|
-
{ allowSingleLine: true }
|
|
803
|
-
],
|
|
804
|
-
"@stylistic/indent": [
|
|
805
|
-
"error",
|
|
806
|
-
2,
|
|
807
|
-
{ ignoredNodes: ["TSMappedType > *"] }
|
|
808
|
-
],
|
|
809
|
-
"@stylistic/jsx-tag-spacing": [
|
|
810
|
-
"error",
|
|
811
|
-
{
|
|
812
|
-
afterOpening: "never",
|
|
813
|
-
beforeClosing: "never",
|
|
814
|
-
beforeSelfClosing: "never",
|
|
815
|
-
closingSlash: "never"
|
|
816
|
-
}
|
|
817
|
-
],
|
|
818
|
-
"@stylistic/jsx-wrap-multilines": "off",
|
|
819
|
-
"@stylistic/lines-between-class-members": "off",
|
|
820
|
-
"@stylistic/object-curly-newline": [
|
|
821
|
-
"error",
|
|
822
|
-
{ consistent: true }
|
|
823
|
-
],
|
|
824
|
-
"@stylistic/object-curly-spacing": [
|
|
825
|
-
"error",
|
|
826
|
-
"never"
|
|
827
|
-
],
|
|
828
|
-
"@stylistic/operator-linebreak": [
|
|
829
|
-
"error",
|
|
830
|
-
"before",
|
|
831
|
-
{ overrides: { "=": "after" } }
|
|
832
|
-
],
|
|
833
|
-
"@stylistic/quotes": [
|
|
834
|
-
"error",
|
|
835
|
-
"single",
|
|
836
|
-
{ avoidEscape: true }
|
|
837
|
-
],
|
|
838
|
-
"@stylistic/quote-props": [
|
|
839
|
-
"error",
|
|
840
|
-
"as-needed"
|
|
841
|
-
],
|
|
842
|
-
"@stylistic/semi": [
|
|
843
|
-
"error",
|
|
844
|
-
"never",
|
|
845
|
-
{ beforeStatementContinuationChars: "always" }
|
|
846
|
-
],
|
|
847
|
-
"@typescript-eslint/no-empty-function": "off",
|
|
848
|
-
"@typescript-eslint/consistent-indexed-object-style": "off"
|
|
849
|
-
}
|
|
850
|
-
}
|
|
851
|
-
]);
|
|
852
|
-
export {
|
|
853
|
-
CONFIG
|
|
854
|
-
};
|
|
855
|
-
//# sourceMappingURL=index.js.map
|