eslint-plugin-absolute 0.2.7 → 0.2.8
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/package.json +6 -1
- package/.absolutejs/eslint.cache.json +0 -49
- package/.absolutejs/prettier.cache.json +0 -49
- package/.absolutejs/tsconfig.tsbuildinfo +0 -1
- package/.claude/settings.local.json +0 -10
- package/.codex +0 -0
- package/.prettierignore +0 -4
- package/.prettierrc.json +0 -8
- package/eslint.config.mjs +0 -107
- package/src/index.ts +0 -45
- package/src/rules/explicit-object-types.ts +0 -75
- package/src/rules/inline-style-limit.ts +0 -88
- package/src/rules/localize-react-props.ts +0 -454
- package/src/rules/max-depth-extended.ts +0 -153
- package/src/rules/max-jsx-nesting.ts +0 -59
- package/src/rules/min-var-length.ts +0 -360
- package/src/rules/no-button-navigation.ts +0 -270
- package/src/rules/no-explicit-return-types.ts +0 -83
- package/src/rules/no-inline-prop-types.ts +0 -68
- package/src/rules/no-multi-style-objects.ts +0 -80
- package/src/rules/no-nested-jsx-return.ts +0 -205
- package/src/rules/no-or-none-component.ts +0 -63
- package/src/rules/no-transition-cssproperties.ts +0 -131
- package/src/rules/no-unnecessary-div.ts +0 -65
- package/src/rules/no-unnecessary-key.ts +0 -111
- package/src/rules/no-useless-function.ts +0 -56
- package/src/rules/seperate-style-files.ts +0 -79
- package/src/rules/sort-exports.ts +0 -581
- package/src/rules/sort-keys-fixable.ts +0 -1265
- package/src/rules/spring-naming-convention.ts +0 -160
- package/tsconfig.json +0 -17
|
@@ -1,581 +0,0 @@
|
|
|
1
|
-
import { TSESLint, TSESTree } from "@typescript-eslint/utils";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* @fileoverview Enforce that top-level export declarations are sorted.
|
|
5
|
-
*
|
|
6
|
-
* This rule supports the following options:
|
|
7
|
-
* - order: "asc" or "desc" (default: "asc")
|
|
8
|
-
* - caseSensitive: boolean (default: false)
|
|
9
|
-
* - natural: boolean (default: false)
|
|
10
|
-
* - minKeys: integer, minimum number of exports in a contiguous block to check (default: 2)
|
|
11
|
-
* - variablesBeforeFunctions: boolean (default: false)
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
type SortExportsOptions = {
|
|
15
|
-
order?: "asc" | "desc";
|
|
16
|
-
caseSensitive?: boolean;
|
|
17
|
-
natural?: boolean;
|
|
18
|
-
minKeys?: number;
|
|
19
|
-
variablesBeforeFunctions?: boolean;
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
type Options = [SortExportsOptions?];
|
|
23
|
-
|
|
24
|
-
type MessageIds = "alphabetical" | "variablesBeforeFunctions";
|
|
25
|
-
|
|
26
|
-
type ExportItem = {
|
|
27
|
-
name: string;
|
|
28
|
-
node: TSESTree.ExportNamedDeclaration;
|
|
29
|
-
isFunction: boolean;
|
|
30
|
-
text: string;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const SORT_BEFORE = Number.parseInt("-1", 10);
|
|
34
|
-
|
|
35
|
-
const hasStringTypeProperty = (value: object) => {
|
|
36
|
-
const maybeType = Reflect.get(value, "type");
|
|
37
|
-
return typeof maybeType === "string";
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const isNodeLike = (value: unknown): value is TSESTree.Node =>
|
|
41
|
-
value !== null &&
|
|
42
|
-
value !== undefined &&
|
|
43
|
-
typeof value === "object" &&
|
|
44
|
-
"type" in value &&
|
|
45
|
-
hasStringTypeProperty(value);
|
|
46
|
-
|
|
47
|
-
const shouldSkipNodeEntry = (key: string, value: unknown) =>
|
|
48
|
-
key === "parent" || value === null || value === undefined;
|
|
49
|
-
|
|
50
|
-
const visitNodeArray = (
|
|
51
|
-
values: unknown[],
|
|
52
|
-
visit: (node: TSESTree.Node | null | undefined) => void
|
|
53
|
-
) => values.filter(isNodeLike).forEach(visit);
|
|
54
|
-
|
|
55
|
-
const visitNodeEntryValue = (
|
|
56
|
-
value: unknown,
|
|
57
|
-
visit: (node: TSESTree.Node | null | undefined) => void
|
|
58
|
-
) => {
|
|
59
|
-
if (Array.isArray(value)) {
|
|
60
|
-
visitNodeArray(value, visit);
|
|
61
|
-
return;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
if (isNodeLike(value)) {
|
|
65
|
-
visit(value);
|
|
66
|
-
}
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
const visitNodeEntries = (
|
|
70
|
-
current: TSESTree.Node,
|
|
71
|
-
visit: (node: TSESTree.Node | null | undefined) => void
|
|
72
|
-
) =>
|
|
73
|
-
Object.entries(current)
|
|
74
|
-
.filter(([key, value]) => !shouldSkipNodeEntry(key, value))
|
|
75
|
-
.forEach(([, value]) => {
|
|
76
|
-
visitNodeEntryValue(value, visit);
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
const getVariableDeclaratorName = (
|
|
80
|
-
declaration: TSESTree.VariableDeclaration
|
|
81
|
-
) => {
|
|
82
|
-
if (declaration.declarations.length !== 1) {
|
|
83
|
-
return null;
|
|
84
|
-
}
|
|
85
|
-
const [firstDeclarator] = declaration.declarations;
|
|
86
|
-
if (firstDeclarator && firstDeclarator.id.type === "Identifier") {
|
|
87
|
-
return firstDeclarator.id.name;
|
|
88
|
-
}
|
|
89
|
-
return null;
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const getDeclarationName = (
|
|
93
|
-
declaration: TSESTree.ExportNamedDeclaration["declaration"]
|
|
94
|
-
) => {
|
|
95
|
-
if (!declaration) {
|
|
96
|
-
return null;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
if (declaration.type === "VariableDeclaration") {
|
|
100
|
-
return getVariableDeclaratorName(declaration);
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
if (
|
|
104
|
-
(declaration.type === "FunctionDeclaration" ||
|
|
105
|
-
declaration.type === "ClassDeclaration") &&
|
|
106
|
-
declaration.id &&
|
|
107
|
-
declaration.id.type === "Identifier"
|
|
108
|
-
) {
|
|
109
|
-
return declaration.id.name;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
return null;
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
const getSpecifierName = (node: TSESTree.ExportNamedDeclaration) => {
|
|
116
|
-
if (node.specifiers.length !== 1) {
|
|
117
|
-
return null;
|
|
118
|
-
}
|
|
119
|
-
const [spec] = node.specifiers;
|
|
120
|
-
if (!spec) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
if (spec.exported.type === "Identifier") {
|
|
124
|
-
return spec.exported.name;
|
|
125
|
-
}
|
|
126
|
-
if (
|
|
127
|
-
spec.exported.type === "Literal" &&
|
|
128
|
-
typeof spec.exported.value === "string"
|
|
129
|
-
) {
|
|
130
|
-
return spec.exported.value;
|
|
131
|
-
}
|
|
132
|
-
return null;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
const getExportName = (node: TSESTree.ExportNamedDeclaration) =>
|
|
136
|
-
getDeclarationName(node.declaration) ?? getSpecifierName(node);
|
|
137
|
-
|
|
138
|
-
const isFixableExport = (exportNode: TSESTree.ExportNamedDeclaration) => {
|
|
139
|
-
const { declaration } = exportNode;
|
|
140
|
-
|
|
141
|
-
if (!declaration) {
|
|
142
|
-
return exportNode.specifiers.length === 1;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
if (
|
|
146
|
-
declaration.type === "VariableDeclaration" &&
|
|
147
|
-
declaration.declarations.length === 1
|
|
148
|
-
) {
|
|
149
|
-
const [firstDecl] = declaration.declarations;
|
|
150
|
-
return firstDecl !== undefined && firstDecl.id.type === "Identifier";
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
return (
|
|
154
|
-
(declaration.type === "FunctionDeclaration" ||
|
|
155
|
-
declaration.type === "ClassDeclaration") &&
|
|
156
|
-
declaration.id !== null &&
|
|
157
|
-
declaration.id.type === "Identifier"
|
|
158
|
-
);
|
|
159
|
-
};
|
|
160
|
-
|
|
161
|
-
const visitImmediateReferences = (
|
|
162
|
-
node: TSESTree.Node | null | undefined,
|
|
163
|
-
onReference: (name: string) => void
|
|
164
|
-
) => {
|
|
165
|
-
if (!node) {
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
const visit = (current: TSESTree.Node | null | undefined) => {
|
|
170
|
-
if (!current) {
|
|
171
|
-
return;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
switch (current.type) {
|
|
175
|
-
case "Identifier":
|
|
176
|
-
onReference(current.name);
|
|
177
|
-
return;
|
|
178
|
-
case "FunctionDeclaration":
|
|
179
|
-
case "FunctionExpression":
|
|
180
|
-
case "ArrowFunctionExpression":
|
|
181
|
-
return;
|
|
182
|
-
case "MemberExpression":
|
|
183
|
-
visit(current.object);
|
|
184
|
-
if (current.computed) {
|
|
185
|
-
visit(current.property);
|
|
186
|
-
}
|
|
187
|
-
return;
|
|
188
|
-
case "Property":
|
|
189
|
-
if (current.computed) {
|
|
190
|
-
visit(current.key);
|
|
191
|
-
}
|
|
192
|
-
visit(current.value);
|
|
193
|
-
return;
|
|
194
|
-
case "PropertyDefinition":
|
|
195
|
-
if (current.computed) {
|
|
196
|
-
visit(current.key);
|
|
197
|
-
}
|
|
198
|
-
if (current.static) {
|
|
199
|
-
visit(current.value);
|
|
200
|
-
}
|
|
201
|
-
return;
|
|
202
|
-
case "MethodDefinition":
|
|
203
|
-
if (current.computed) {
|
|
204
|
-
visit(current.key);
|
|
205
|
-
}
|
|
206
|
-
return;
|
|
207
|
-
case "StaticBlock":
|
|
208
|
-
for (const statement of current.body) {
|
|
209
|
-
visit(statement);
|
|
210
|
-
}
|
|
211
|
-
return;
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
visitNodeEntries(current, visit);
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
visit(node);
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
const getImmediateDependencyNames = (node: TSESTree.ExportNamedDeclaration) => {
|
|
221
|
-
const names = new Set<string>();
|
|
222
|
-
const { declaration } = node;
|
|
223
|
-
const addName = names.add.bind(names);
|
|
224
|
-
const addDeclaratorDependencies = (
|
|
225
|
-
declarator: TSESTree.VariableDeclarator
|
|
226
|
-
) => visitImmediateReferences(declarator.init, addName);
|
|
227
|
-
const addClassElementDependencies = (
|
|
228
|
-
element: TSESTree.ClassElement | TSESTree.StaticBlock
|
|
229
|
-
) => visitImmediateReferences(element, addName);
|
|
230
|
-
|
|
231
|
-
if (!declaration) {
|
|
232
|
-
return names;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
if (declaration.type === "VariableDeclaration") {
|
|
236
|
-
declaration.declarations.forEach(addDeclaratorDependencies);
|
|
237
|
-
return names;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
if (declaration.type === "ClassDeclaration") {
|
|
241
|
-
visitImmediateReferences(declaration.superClass, addName);
|
|
242
|
-
declaration.body.body.forEach(addClassElementDependencies);
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
return names;
|
|
246
|
-
};
|
|
247
|
-
|
|
248
|
-
export const sortExports: TSESLint.RuleModule<MessageIds, Options> = {
|
|
249
|
-
create(context) {
|
|
250
|
-
const { sourceCode } = context;
|
|
251
|
-
const [option] = context.options;
|
|
252
|
-
|
|
253
|
-
const order: "asc" | "desc" =
|
|
254
|
-
option && option.order ? option.order : "asc";
|
|
255
|
-
|
|
256
|
-
const caseSensitive =
|
|
257
|
-
option && typeof option.caseSensitive === "boolean"
|
|
258
|
-
? option.caseSensitive
|
|
259
|
-
: false;
|
|
260
|
-
|
|
261
|
-
const natural =
|
|
262
|
-
option && typeof option.natural === "boolean"
|
|
263
|
-
? option.natural
|
|
264
|
-
: false;
|
|
265
|
-
|
|
266
|
-
const minKeys =
|
|
267
|
-
option && typeof option.minKeys === "number" ? option.minKeys : 2;
|
|
268
|
-
|
|
269
|
-
const variablesBeforeFunctions =
|
|
270
|
-
option && typeof option.variablesBeforeFunctions === "boolean"
|
|
271
|
-
? option.variablesBeforeFunctions
|
|
272
|
-
: false;
|
|
273
|
-
|
|
274
|
-
const generateExportText = (node: TSESTree.ExportNamedDeclaration) =>
|
|
275
|
-
sourceCode
|
|
276
|
-
.getText(node)
|
|
277
|
-
.trim()
|
|
278
|
-
.replace(/\s*;?\s*$/, ";");
|
|
279
|
-
|
|
280
|
-
const compareStrings = (strLeft: string, strRight: string) => {
|
|
281
|
-
let left = strLeft;
|
|
282
|
-
let right = strRight;
|
|
283
|
-
|
|
284
|
-
if (!caseSensitive) {
|
|
285
|
-
left = left.toLowerCase();
|
|
286
|
-
right = right.toLowerCase();
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
const cmp = natural
|
|
290
|
-
? left.localeCompare(right, undefined, { numeric: true })
|
|
291
|
-
: left.localeCompare(right);
|
|
292
|
-
|
|
293
|
-
return order === "asc" ? cmp : -cmp;
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
const isFunctionExport = (node: TSESTree.ExportNamedDeclaration) => {
|
|
297
|
-
const { declaration } = node;
|
|
298
|
-
|
|
299
|
-
if (!declaration) {
|
|
300
|
-
return false;
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
if (declaration.type === "FunctionDeclaration") {
|
|
304
|
-
return true;
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
if (declaration.type !== "VariableDeclaration") {
|
|
308
|
-
return false;
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
if (declaration.declarations.length !== 1) {
|
|
312
|
-
return false;
|
|
313
|
-
}
|
|
314
|
-
|
|
315
|
-
const [firstDeclarator] = declaration.declarations;
|
|
316
|
-
if (!firstDeclarator) {
|
|
317
|
-
return false;
|
|
318
|
-
}
|
|
319
|
-
const { init } = firstDeclarator;
|
|
320
|
-
if (!init) {
|
|
321
|
-
return false;
|
|
322
|
-
}
|
|
323
|
-
return (
|
|
324
|
-
init.type === "FunctionExpression" ||
|
|
325
|
-
init.type === "ArrowFunctionExpression"
|
|
326
|
-
);
|
|
327
|
-
};
|
|
328
|
-
|
|
329
|
-
const sortComparator = (left: ExportItem, right: ExportItem) => {
|
|
330
|
-
const kindA = left.node.exportKind ?? "value";
|
|
331
|
-
const kindB = right.node.exportKind ?? "value";
|
|
332
|
-
|
|
333
|
-
if (kindA !== kindB) {
|
|
334
|
-
return kindA === "type" ? SORT_BEFORE : 1;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
if (
|
|
338
|
-
variablesBeforeFunctions &&
|
|
339
|
-
left.isFunction !== right.isFunction
|
|
340
|
-
) {
|
|
341
|
-
return left.isFunction ? 1 : SORT_BEFORE;
|
|
342
|
-
}
|
|
343
|
-
|
|
344
|
-
return compareStrings(left.name, right.name);
|
|
345
|
-
};
|
|
346
|
-
|
|
347
|
-
const buildItems = (block: TSESTree.ExportNamedDeclaration[]) =>
|
|
348
|
-
block
|
|
349
|
-
.map((node) => {
|
|
350
|
-
const name = getExportName(node);
|
|
351
|
-
if (!name) {
|
|
352
|
-
return null;
|
|
353
|
-
}
|
|
354
|
-
const item: ExportItem = {
|
|
355
|
-
isFunction: isFunctionExport(node),
|
|
356
|
-
name,
|
|
357
|
-
node,
|
|
358
|
-
text: sourceCode.getText(node)
|
|
359
|
-
};
|
|
360
|
-
return item;
|
|
361
|
-
})
|
|
362
|
-
.filter((item): item is ExportItem => item !== null);
|
|
363
|
-
|
|
364
|
-
const findFirstUnsorted = (items: ExportItem[]) => {
|
|
365
|
-
let messageId: MessageIds = "alphabetical";
|
|
366
|
-
|
|
367
|
-
const unsorted = items.some((current, idx) => {
|
|
368
|
-
if (idx === 0) {
|
|
369
|
-
return false;
|
|
370
|
-
}
|
|
371
|
-
const prev = items[idx - 1];
|
|
372
|
-
if (!prev) {
|
|
373
|
-
return false;
|
|
374
|
-
}
|
|
375
|
-
if (sortComparator(prev, current) <= 0) {
|
|
376
|
-
return false;
|
|
377
|
-
}
|
|
378
|
-
if (
|
|
379
|
-
variablesBeforeFunctions &&
|
|
380
|
-
prev.isFunction &&
|
|
381
|
-
!current.isFunction
|
|
382
|
-
) {
|
|
383
|
-
messageId = "variablesBeforeFunctions";
|
|
384
|
-
}
|
|
385
|
-
return true;
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
return unsorted ? messageId : null;
|
|
389
|
-
};
|
|
390
|
-
|
|
391
|
-
const hasForwardDependenciesInOrder = (items: ExportItem[]) => {
|
|
392
|
-
const exportNames = items.map((item) => item.name);
|
|
393
|
-
return items.some((item, idx) => {
|
|
394
|
-
const laterNames = new Set(exportNames.slice(idx + 1));
|
|
395
|
-
if (laterNames.size === 0) {
|
|
396
|
-
return false;
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
const dependencies = getImmediateDependencyNames(item.node);
|
|
400
|
-
for (const dependency of dependencies) {
|
|
401
|
-
if (laterNames.has(dependency)) {
|
|
402
|
-
return true;
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
return false;
|
|
406
|
-
});
|
|
407
|
-
};
|
|
408
|
-
|
|
409
|
-
const wouldCreateForwardDependencies = (
|
|
410
|
-
items: ExportItem[],
|
|
411
|
-
sortedItems: ExportItem[]
|
|
412
|
-
) => {
|
|
413
|
-
const sortedIndices = new Map(
|
|
414
|
-
sortedItems.map((item, idx) => [item.name, idx])
|
|
415
|
-
);
|
|
416
|
-
const exportNames = new Set(items.map((item) => item.name));
|
|
417
|
-
|
|
418
|
-
return items.some((item) => {
|
|
419
|
-
const itemIndex = sortedIndices.get(item.name);
|
|
420
|
-
if (itemIndex === undefined) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
|
|
424
|
-
const dependencies = getImmediateDependencyNames(item.node);
|
|
425
|
-
for (const dependency of dependencies) {
|
|
426
|
-
const dependencyIndex = exportNames.has(dependency)
|
|
427
|
-
? sortedIndices.get(dependency)
|
|
428
|
-
: undefined;
|
|
429
|
-
if (
|
|
430
|
-
dependencyIndex !== undefined &&
|
|
431
|
-
itemIndex < dependencyIndex
|
|
432
|
-
)
|
|
433
|
-
return true;
|
|
434
|
-
}
|
|
435
|
-
|
|
436
|
-
return false;
|
|
437
|
-
});
|
|
438
|
-
};
|
|
439
|
-
|
|
440
|
-
const processExportBlock = (
|
|
441
|
-
block: TSESTree.ExportNamedDeclaration[]
|
|
442
|
-
) => {
|
|
443
|
-
if (block.length < minKeys) {
|
|
444
|
-
return;
|
|
445
|
-
}
|
|
446
|
-
|
|
447
|
-
const items = buildItems(block);
|
|
448
|
-
|
|
449
|
-
if (items.length < minKeys) {
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
|
|
453
|
-
const messageId = findFirstUnsorted(items);
|
|
454
|
-
if (!messageId) {
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
|
|
458
|
-
if (hasForwardDependenciesInOrder(items)) {
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
const sortedItems = items.slice().sort(sortComparator);
|
|
463
|
-
|
|
464
|
-
if (wouldCreateForwardDependencies(items, sortedItems)) {
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
const expectedOrder = sortedItems
|
|
469
|
-
.map((item) => item.name)
|
|
470
|
-
.join(", ");
|
|
471
|
-
|
|
472
|
-
const [firstNode] = block;
|
|
473
|
-
const lastNode = block[block.length - 1];
|
|
474
|
-
|
|
475
|
-
if (!firstNode || !lastNode) {
|
|
476
|
-
return;
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
context.report({
|
|
480
|
-
data: {
|
|
481
|
-
expectedOrder
|
|
482
|
-
},
|
|
483
|
-
fix(fixer) {
|
|
484
|
-
const fixableNodes = block.filter(isFixableExport);
|
|
485
|
-
|
|
486
|
-
if (fixableNodes.length < minKeys) {
|
|
487
|
-
return null;
|
|
488
|
-
}
|
|
489
|
-
|
|
490
|
-
const sortedText = sortedItems
|
|
491
|
-
.map((item) => generateExportText(item.node))
|
|
492
|
-
.join("\n");
|
|
493
|
-
|
|
494
|
-
const [rangeStart] = firstNode.range;
|
|
495
|
-
const [, rangeEnd] = lastNode.range;
|
|
496
|
-
|
|
497
|
-
const fullText = sourceCode.getText();
|
|
498
|
-
const originalText = fullText.slice(rangeStart, rangeEnd);
|
|
499
|
-
|
|
500
|
-
if (originalText === sortedText) {
|
|
501
|
-
return null;
|
|
502
|
-
}
|
|
503
|
-
|
|
504
|
-
return fixer.replaceTextRange(
|
|
505
|
-
[rangeStart, rangeEnd],
|
|
506
|
-
sortedText
|
|
507
|
-
);
|
|
508
|
-
},
|
|
509
|
-
messageId,
|
|
510
|
-
node: firstNode
|
|
511
|
-
});
|
|
512
|
-
};
|
|
513
|
-
|
|
514
|
-
return {
|
|
515
|
-
"Program:exit"(node: TSESTree.Program) {
|
|
516
|
-
const { body } = node;
|
|
517
|
-
const block: TSESTree.ExportNamedDeclaration[] = [];
|
|
518
|
-
|
|
519
|
-
body.forEach((stmt) => {
|
|
520
|
-
if (
|
|
521
|
-
stmt.type === "ExportNamedDeclaration" &&
|
|
522
|
-
!stmt.source &&
|
|
523
|
-
getExportName(stmt) !== null
|
|
524
|
-
) {
|
|
525
|
-
block.push(stmt);
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
|
|
529
|
-
if (block.length > 0) {
|
|
530
|
-
processExportBlock(block);
|
|
531
|
-
block.length = 0;
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
|
|
535
|
-
if (block.length > 0) {
|
|
536
|
-
processExportBlock(block);
|
|
537
|
-
}
|
|
538
|
-
}
|
|
539
|
-
};
|
|
540
|
-
},
|
|
541
|
-
defaultOptions: [{}],
|
|
542
|
-
meta: {
|
|
543
|
-
docs: {
|
|
544
|
-
description:
|
|
545
|
-
"Enforce that top-level export declarations are sorted by exported name and, optionally, that variable exports come before function exports"
|
|
546
|
-
},
|
|
547
|
-
fixable: "code",
|
|
548
|
-
messages: {
|
|
549
|
-
alphabetical:
|
|
550
|
-
"Export declarations are not sorted alphabetically. Expected order: {{expectedOrder}}.",
|
|
551
|
-
variablesBeforeFunctions:
|
|
552
|
-
"Non-function exports should come before function exports."
|
|
553
|
-
},
|
|
554
|
-
schema: [
|
|
555
|
-
{
|
|
556
|
-
additionalProperties: false,
|
|
557
|
-
properties: {
|
|
558
|
-
caseSensitive: {
|
|
559
|
-
type: "boolean"
|
|
560
|
-
},
|
|
561
|
-
minKeys: {
|
|
562
|
-
minimum: 2,
|
|
563
|
-
type: "integer"
|
|
564
|
-
},
|
|
565
|
-
natural: {
|
|
566
|
-
type: "boolean"
|
|
567
|
-
},
|
|
568
|
-
order: {
|
|
569
|
-
enum: ["asc", "desc"],
|
|
570
|
-
type: "string"
|
|
571
|
-
},
|
|
572
|
-
variablesBeforeFunctions: {
|
|
573
|
-
type: "boolean"
|
|
574
|
-
}
|
|
575
|
-
},
|
|
576
|
-
type: "object"
|
|
577
|
-
}
|
|
578
|
-
],
|
|
579
|
-
type: "suggestion"
|
|
580
|
-
}
|
|
581
|
-
};
|