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