@so1ve/eslint-plugin 4.0.1 → 4.1.0

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/dist/index.d.mts CHANGED
@@ -1,53 +1,65 @@
1
1
  import { ESLintUtils } from "@typescript-eslint/utils";
2
2
 
3
3
  //#region src/rules/function-style.d.ts
4
- type MessageIds$10 = "arrow" | "declaration";
4
+ type MessageIds$12 = "arrow" | "declaration";
5
+ type Options$12 = [];
6
+ declare const rule$12: ESLintUtils.RuleModule<MessageIds$12, Options$12>;
7
+ //#endregion
8
+ //#region src/rules/html-spaced-comment.d.ts
9
+ type MessageIds$11 = "expectedSpaceBefore" | "expectedSpaceAfter";
10
+ type Options$11 = [];
11
+ declare const rule$11: ESLintUtils.RuleModule<MessageIds$11, Options$11>;
12
+ //#endregion
13
+ //#region src/rules/import-dedupe.d.ts
14
+ type MessageIds$10 = "importDedupe";
5
15
  type Options$10 = [];
6
16
  declare const rule$10: ESLintUtils.RuleModule<MessageIds$10, Options$10>;
7
17
  //#endregion
8
- //#region src/rules/html-spaced-comment.d.ts
9
- type MessageIds$9 = "expectedSpaceBefore" | "expectedSpaceAfter";
18
+ //#region src/rules/import-export-newline.d.ts
19
+ type MessageIds$9 = "newlineAfterLastImport" | "newlineBeforeExport" | "newlineAfterExport";
10
20
  type Options$9 = [];
11
21
  declare const rule$9: ESLintUtils.RuleModule<MessageIds$9, Options$9>;
12
22
  //#endregion
13
- //#region src/rules/import-dedupe.d.ts
14
- type MessageIds$8 = "importDedupe";
23
+ //#region src/rules/no-import-promises-as.d.ts
24
+ type MessageIds$8 = "noImportPromisesAs";
15
25
  type Options$8 = [];
16
26
  declare const rule$8: ESLintUtils.RuleModule<MessageIds$8, Options$8>;
17
27
  //#endregion
18
- //#region src/rules/import-export-newline.d.ts
19
- type MessageIds$7 = "newlineAfterLastImport" | "newlineBeforeExport" | "newlineAfterExport";
28
+ //#region src/rules/no-inline-type-modifier.d.ts
29
+ type MessageIds$7 = "noInlineTypeModifier";
20
30
  type Options$7 = [];
21
31
  declare const rule$7: ESLintUtils.RuleModule<MessageIds$7, Options$7>;
22
32
  //#endregion
23
- //#region src/rules/no-import-promises-as.d.ts
24
- type MessageIds$6 = "noImportPromisesAs";
33
+ //#region src/rules/no-negated-comparison.d.ts
34
+ type MessageIds$6 = "noNegatedComparison";
25
35
  type Options$6 = [];
26
36
  declare const rule$6: ESLintUtils.RuleModule<MessageIds$6, Options$6>;
27
37
  //#endregion
28
- //#region src/rules/no-inline-type-import.d.ts
29
- type MessageIds$5 = "noInlineTypeImport";
38
+ //#region src/rules/no-useless-template-string.d.ts
39
+ type MessageIds$5 = "noUselessTemplateString";
30
40
  type Options$5 = [];
31
41
  declare const rule$5: ESLintUtils.RuleModule<MessageIds$5, Options$5>;
32
42
  //#endregion
33
- //#region src/rules/no-negated-comparison.d.ts
34
- type MessageIds$4 = "noNegatedComparison";
43
+ //#region src/rules/prefer-ts-expect-error.d.ts
44
+ type MessageIds$4 = "preferExpectErrorComment";
35
45
  type Options$4 = [];
36
46
  declare const rule$4: ESLintUtils.RuleModule<MessageIds$4, Options$4>;
37
47
  //#endregion
38
- //#region src/rules/no-useless-template-string.d.ts
39
- type MessageIds$3 = "noUselessTemplateString";
48
+ //#region src/rules/require-async-with-await.d.ts
49
+ type MessageIds$3 = "requireAsyncWithAwait";
40
50
  type Options$3 = [];
41
51
  declare const rule$3: ESLintUtils.RuleModule<MessageIds$3, Options$3>;
42
52
  //#endregion
43
- //#region src/rules/prefer-ts-expect-error.d.ts
44
- type MessageIds$2 = "preferExpectErrorComment";
53
+ //#region src/rules/sort-exports.d.ts
54
+ type MessageIds$2 = "sort";
45
55
  type Options$2 = [];
46
56
  declare const rule$2: ESLintUtils.RuleModule<MessageIds$2, Options$2>;
47
57
  //#endregion
48
- //#region src/rules/require-async-with-await.d.ts
49
- type MessageIds$1 = "requireAsyncWithAwait";
50
- type Options$1 = [];
58
+ //#region src/rules/sort-imports.d.ts
59
+ type MessageIds$1 = "sort";
60
+ type Options$1 = [{
61
+ groups?: string[][];
62
+ }];
51
63
  declare const rule$1: ESLintUtils.RuleModule<MessageIds$1, Options$1>;
52
64
  //#endregion
53
65
  //#region src/rules/vue-root-element-sort-attributes.d.ts
@@ -61,16 +73,18 @@ declare const rule: ESLintUtils.RuleModule<MessageIds, Options>;
61
73
  //#region src/index.d.ts
62
74
  declare const _default: {
63
75
  rules: {
64
- "function-style": typeof rule$10;
65
- "html-spaced-comment": typeof rule$9;
66
- "import-dedupe": typeof rule$8;
67
- "import-export-newline": typeof rule$7;
68
- "no-import-promises-as": typeof rule$6;
69
- "no-inline-type-import": typeof rule$5;
70
- "no-negated-comparison": typeof rule$4;
71
- "no-useless-template-string": typeof rule$3;
72
- "prefer-ts-expect-error": typeof rule$2;
73
- "require-async-with-await": typeof rule$1;
76
+ "function-style": typeof rule$12;
77
+ "html-spaced-comment": typeof rule$11;
78
+ "import-dedupe": typeof rule$10;
79
+ "import-export-newline": typeof rule$9;
80
+ "no-import-promises-as": typeof rule$8;
81
+ "no-inline-type-modifier": typeof rule$7;
82
+ "no-negated-comparison": typeof rule$6;
83
+ "no-useless-template-string": typeof rule$5;
84
+ "prefer-ts-expect-error": typeof rule$4;
85
+ "require-async-with-await": typeof rule$3;
86
+ "sort-exports": typeof rule$2;
87
+ "sort-imports": typeof rule$1;
74
88
  "vue-root-element-sort-attributes": typeof rule;
75
89
  };
76
90
  };
package/dist/index.mjs CHANGED
@@ -1,5 +1,6 @@
1
1
  import { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/types";
2
2
  import { AST_TOKEN_TYPES, ESLintUtils } from "@typescript-eslint/utils";
3
+ import natsort from "natsort";
3
4
 
4
5
  //#region src/utils/index.ts
5
6
  const createEslintRule = ESLintUtils.RuleCreator((ruleName) => ruleName);
@@ -18,9 +19,9 @@ const getNextNode = (node) => getSiblingNode(node, 1);
18
19
 
19
20
  //#endregion
20
21
  //#region src/rules/function-style.ts
21
- const RULE_NAME$9 = "function-style";
22
- const rule$10 = createEslintRule({
23
- name: RULE_NAME$9,
22
+ const RULE_NAME$11 = "function-style";
23
+ const rule$12 = createEslintRule({
24
+ name: RULE_NAME$11,
24
25
  meta: {
25
26
  type: "problem",
26
27
  docs: { description: "Enforce function style." },
@@ -155,13 +156,13 @@ const rule$10 = createEslintRule({
155
156
  };
156
157
  }
157
158
  });
158
- var function_style_default = rule$10;
159
+ var function_style_default = rule$12;
159
160
 
160
161
  //#endregion
161
162
  //#region src/rules/html-spaced-comment.ts
162
- const RULE_NAME$8 = "html-spaced-comment";
163
- const rule$9 = createEslintRule({
164
- name: RULE_NAME$8,
163
+ const RULE_NAME$10 = "html-spaced-comment";
164
+ const rule$11 = createEslintRule({
165
+ name: RULE_NAME$10,
165
166
  meta: {
166
167
  type: "layout",
167
168
  docs: { description: "Enforce consistent spacing in HTML comments" },
@@ -193,13 +194,13 @@ const rule$9 = createEslintRule({
193
194
  });
194
195
  } })
195
196
  });
196
- var html_spaced_comment_default = rule$9;
197
+ var html_spaced_comment_default = rule$11;
197
198
 
198
199
  //#endregion
199
200
  //#region src/rules/import-dedupe.ts
200
- const RULE_NAME$7 = "import-dedupe";
201
- const rule$8 = createEslintRule({
202
- name: RULE_NAME$7,
201
+ const RULE_NAME$9 = "import-dedupe";
202
+ const rule$10 = createEslintRule({
203
+ name: RULE_NAME$9,
203
204
  meta: {
204
205
  type: "problem",
205
206
  docs: { description: "Fix duplication in imports." },
@@ -232,14 +233,14 @@ const rule$8 = createEslintRule({
232
233
  }
233
234
  } })
234
235
  });
235
- var import_dedupe_default = rule$8;
236
+ var import_dedupe_default = rule$10;
236
237
 
237
238
  //#endregion
238
239
  //#region src/rules/import-export-newline.ts
239
- const RULE_NAME$6 = "import-export-newline";
240
+ const RULE_NAME$8 = "import-export-newline";
240
241
  const isExportDeclaration = (node) => node.type === "ExportNamedDeclaration" || node.type === "ExportDefaultDeclaration" || node.type === "ExportAllDeclaration";
241
- const rule$7 = createEslintRule({
242
- name: RULE_NAME$6,
242
+ const rule$9 = createEslintRule({
243
+ name: RULE_NAME$8,
243
244
  meta: {
244
245
  type: "problem",
245
246
  docs: { description: "Enforce spacing between imports and exports." },
@@ -327,19 +328,19 @@ const rule$7 = createEslintRule({
327
328
  };
328
329
  }
329
330
  });
330
- var import_export_newline_default = rule$7;
331
+ var import_export_newline_default = rule$9;
331
332
 
332
333
  //#endregion
333
334
  //#region src/rules/no-import-promises-as.ts
334
- const RULE_NAME$5 = "no-import-promises-as";
335
+ const RULE_NAME$7 = "no-import-promises-as";
335
336
  const POSSIBLE_IMPORT_SOURCES = [
336
337
  "dns",
337
338
  "fs",
338
339
  "readline",
339
340
  "stream"
340
341
  ].flatMap((s) => [s, `node:${s}`]);
341
- const rule$6 = createEslintRule({
342
- name: RULE_NAME$5,
342
+ const rule$8 = createEslintRule({
343
+ name: RULE_NAME$7,
343
344
  meta: {
344
345
  type: "problem",
345
346
  docs: { description: "Disallow import promises as." },
@@ -369,74 +370,93 @@ const rule$6 = createEslintRule({
369
370
  } };
370
371
  }
371
372
  });
372
- var no_import_promises_as_default = rule$6;
373
+ var no_import_promises_as_default = rule$8;
373
374
 
374
375
  //#endregion
375
- //#region src/rules/no-inline-type-import.ts
376
- const RULE_NAME$4 = "no-inline-type-import";
377
- function generateImportsText(specifiers) {
378
- let text = "{ ";
379
- const texts = [];
380
- for (const s of specifiers) {
381
- const importedName = s.imported.type === AST_NODE_TYPES.Identifier ? s.imported.name : s.imported.raw;
382
- texts.push(importedName === s.local.name ? s.local.name : `${importedName} as ${s.local.name}`);
383
- }
384
- text += texts.join(", ");
385
- text += " }";
386
- return text;
387
- }
388
- function generateTypeImportText(typeSpecifiers) {
389
- let text = "type ";
390
- text += generateImportsText(typeSpecifiers);
391
- return text;
392
- }
393
- function generateValueImportText(defaultImportSpecifier, valueSpecifiers) {
394
- const hasValueImport = valueSpecifiers.length > 0;
395
- let text = "";
396
- if (defaultImportSpecifier) {
397
- text += defaultImportSpecifier.local.name;
398
- if (hasValueImport) text += ", ";
399
- }
400
- if (hasValueImport) text += generateImportsText(valueSpecifiers);
401
- return text;
376
+ //#region src/rules/no-inline-type-modifier.ts
377
+ const RULE_NAME$6 = "no-inline-type-modifier";
378
+ const getName = (node) => node.type === AST_NODE_TYPES.Identifier ? node.name : node.raw;
379
+ function getSpecifierText(s) {
380
+ const isExport = s.type === AST_NODE_TYPES.ExportSpecifier;
381
+ const name1 = getName(isExport ? s.local : s.imported);
382
+ const name2 = getName(isExport ? s.exported : s.local);
383
+ return name1 === name2 ? name1 : `${name1} as ${name2}`;
402
384
  }
403
- const rule$5 = createEslintRule({
404
- name: RULE_NAME$4,
385
+ function generateSpecifiersText(specifiers) {
386
+ return `{ ${specifiers.map(getSpecifierText).join(", ")} }`;
387
+ }
388
+ const generateTypeText = (specifiers) => `type ${generateSpecifiersText(specifiers)}`;
389
+ function generateValueText(valueSpecifiers, defaultSpecifier) {
390
+ const parts = [];
391
+ if (defaultSpecifier) parts.push(defaultSpecifier.local.name);
392
+ if (valueSpecifiers.length > 0) parts.push(generateSpecifiersText(valueSpecifiers));
393
+ return parts.join(", ");
394
+ }
395
+ function classifySpecifiers(specifiers) {
396
+ const typeSpecifiers = [];
397
+ const valueSpecifiers = [];
398
+ let defaultSpecifier;
399
+ for (const s of specifiers) if (s.type === AST_NODE_TYPES.ImportDefaultSpecifier) defaultSpecifier = s;
400
+ else if (s.type === AST_NODE_TYPES.ImportSpecifier) if (s.importKind === "type") typeSpecifiers.push(s);
401
+ else valueSpecifiers.push(s);
402
+ else if (s.type === AST_NODE_TYPES.ExportSpecifier) if (s.exportKind === "type") typeSpecifiers.push(s);
403
+ else valueSpecifiers.push(s);
404
+ return {
405
+ typeSpecifiers,
406
+ valueSpecifiers,
407
+ defaultSpecifier
408
+ };
409
+ }
410
+ const rule$7 = createEslintRule({
411
+ name: RULE_NAME$6,
405
412
  meta: {
406
413
  type: "layout",
407
- docs: { description: "Disallow inline type import." },
414
+ docs: { description: "Disallow inline type modifiers in import/export." },
408
415
  fixable: "code",
409
416
  schema: [],
410
- messages: { noInlineTypeImport: "Expected no inline type import." }
417
+ messages: { noInlineTypeModifier: "Expected no inline type modifier." }
411
418
  },
412
419
  defaultOptions: [],
413
- create: (context) => ({ ImportDeclaration: (node) => {
414
- const { specifiers } = node;
415
- const typeSpecifiers = specifiers.filter((s) => s.type === AST_NODE_TYPES.ImportSpecifier && s.importKind === "type");
416
- const valueSpecifiers = specifiers.filter((s) => s.type === AST_NODE_TYPES.ImportSpecifier && s.importKind === "value");
417
- const defaultImportSpecifier = specifiers.find((s) => s.type === AST_NODE_TYPES.ImportDefaultSpecifier);
418
- const hasDefaultImport = !!defaultImportSpecifier;
419
- const hasTypeImport = typeSpecifiers.length > 0;
420
- const hasValueImport = valueSpecifiers.length > 0;
421
- if (!hasTypeImport) return;
422
- const texts = [];
423
- texts.push(generateTypeImportText(typeSpecifiers));
424
- if (hasDefaultImport || hasValueImport) texts.push(generateValueImportText(defaultImportSpecifier, valueSpecifiers));
425
- const textToReport = texts.map((text) => `import ${text} from "${node.source.value}";`).join("\n");
426
- context.report({
427
- node,
428
- messageId: "noInlineTypeImport",
429
- fix(fixer) {
430
- return fixer.replaceText(node, textToReport);
431
- }
432
- });
433
- } })
420
+ create: (context) => ({
421
+ ImportDeclaration: (node) => {
422
+ const { typeSpecifiers, valueSpecifiers, defaultSpecifier } = classifySpecifiers(node.specifiers);
423
+ if (typeSpecifiers.length === 0) return;
424
+ const texts = [];
425
+ texts.push(generateTypeText(typeSpecifiers));
426
+ if (defaultSpecifier || valueSpecifiers.length > 0) texts.push(generateValueText(valueSpecifiers, defaultSpecifier));
427
+ const textToReport = texts.map((text) => `import ${text} from "${node.source.value}";`).join("\n");
428
+ context.report({
429
+ node,
430
+ messageId: "noInlineTypeModifier",
431
+ fix(fixer) {
432
+ return fixer.replaceText(node, textToReport);
433
+ }
434
+ });
435
+ },
436
+ ExportNamedDeclaration: (node) => {
437
+ if (node.declaration || node.exportKind === "type") return;
438
+ const { typeSpecifiers, valueSpecifiers } = classifySpecifiers(node.specifiers);
439
+ if (typeSpecifiers.length === 0) return;
440
+ const fromText = node.source ? ` from "${node.source.value}"` : "";
441
+ const texts = [];
442
+ texts.push(generateTypeText(typeSpecifiers));
443
+ if (valueSpecifiers.length > 0) texts.push(generateValueText(valueSpecifiers));
444
+ const textToReport = texts.map((text) => `export ${text}${fromText};`).join("\n");
445
+ context.report({
446
+ node,
447
+ messageId: "noInlineTypeModifier",
448
+ fix(fixer) {
449
+ return fixer.replaceText(node, textToReport);
450
+ }
451
+ });
452
+ }
453
+ })
434
454
  });
435
- var no_inline_type_import_default = rule$5;
455
+ var no_inline_type_modifier_default = rule$7;
436
456
 
437
457
  //#endregion
438
458
  //#region src/rules/no-negated-comparison.ts
439
- const RULE_NAME$3 = "no-negated-comparison";
459
+ const RULE_NAME$5 = "no-negated-comparison";
440
460
  const negatedToPositive = {
441
461
  "==": "!=",
442
462
  "===": "!==",
@@ -448,8 +468,8 @@ const negatedToPositive = {
448
468
  ">=": "<"
449
469
  };
450
470
  const negatives = Object.keys(negatedToPositive);
451
- const rule$4 = createEslintRule({
452
- name: RULE_NAME$3,
471
+ const rule$6 = createEslintRule({
472
+ name: RULE_NAME$5,
453
473
  meta: {
454
474
  type: "problem",
455
475
  docs: { description: "Disallow negated comparison." },
@@ -473,13 +493,13 @@ const rule$4 = createEslintRule({
473
493
  });
474
494
  } })
475
495
  });
476
- var no_negated_comparison_default = rule$4;
496
+ var no_negated_comparison_default = rule$6;
477
497
 
478
498
  //#endregion
479
499
  //#region src/rules/no-useless-template-string.ts
480
- const RULE_NAME$2 = "no-useless-template-string";
481
- const rule$3 = createEslintRule({
482
- name: RULE_NAME$2,
500
+ const RULE_NAME$4 = "no-useless-template-string";
501
+ const rule$5 = createEslintRule({
502
+ name: RULE_NAME$4,
483
503
  meta: {
484
504
  type: "problem",
485
505
  docs: { description: "No useless template string." },
@@ -500,11 +520,11 @@ const rule$3 = createEslintRule({
500
520
  });
501
521
  } })
502
522
  });
503
- var no_useless_template_string_default = rule$3;
523
+ var no_useless_template_string_default = rule$5;
504
524
 
505
525
  //#endregion
506
526
  //#region src/rules/prefer-ts-expect-error.ts
507
- const rule$2 = createEslintRule({
527
+ const rule$4 = createEslintRule({
508
528
  name: "prefer-ts-expect-error",
509
529
  meta: {
510
530
  type: "problem",
@@ -518,15 +538,15 @@ const rule$2 = createEslintRule({
518
538
  create(context) {
519
539
  const tsIgnoreRegExpSingleLine = /^\s*(?:\/\s*)?@ts-ignore/;
520
540
  const tsIgnoreRegExpMultiLine = /^\s*(?:(?:\/|\*)+\s*)?@ts-ignore/;
521
- const isLineComment = (comment) => comment.type === AST_TOKEN_TYPES.Line;
541
+ const isLineComment$1 = (comment) => comment.type === AST_TOKEN_TYPES.Line;
522
542
  function getLastCommentLine(comment) {
523
- if (isLineComment(comment)) return comment.value;
543
+ if (isLineComment$1(comment)) return comment.value;
524
544
  const commentlines = comment.value.split("\n");
525
545
  return commentlines[commentlines.length - 1];
526
546
  }
527
547
  function isValidTsIgnorePresent(comment) {
528
548
  const line = getLastCommentLine(comment);
529
- return isLineComment(comment) ? tsIgnoreRegExpSingleLine.test(line) : tsIgnoreRegExpMultiLine.test(line);
549
+ return isLineComment$1(comment) ? tsIgnoreRegExpSingleLine.test(line) : tsIgnoreRegExpMultiLine.test(line);
530
550
  }
531
551
  return { Program() {
532
552
  const comments = context.sourceCode.getAllComments();
@@ -536,19 +556,19 @@ const rule$2 = createEslintRule({
536
556
  context.report({
537
557
  node: comment,
538
558
  messageId: "preferExpectErrorComment",
539
- fix: isLineComment(comment) ? lineCommentRuleFixer : blockCommentRuleFixer
559
+ fix: isLineComment$1(comment) ? lineCommentRuleFixer : blockCommentRuleFixer
540
560
  });
541
561
  }
542
562
  } };
543
563
  }
544
564
  });
545
- var prefer_ts_expect_error_default = rule$2;
565
+ var prefer_ts_expect_error_default = rule$4;
546
566
 
547
567
  //#endregion
548
568
  //#region src/rules/require-async-with-await.ts
549
- const RULE_NAME$1 = "require-async-with-await";
550
- const rule$1 = createEslintRule({
551
- name: RULE_NAME$1,
569
+ const RULE_NAME$3 = "require-async-with-await";
570
+ const rule$3 = createEslintRule({
571
+ name: RULE_NAME$3,
552
572
  meta: {
553
573
  type: "problem",
554
574
  docs: { description: "Require using async keyword with await." },
@@ -589,7 +609,581 @@ const rule$1 = createEslintRule({
589
609
  };
590
610
  }
591
611
  });
592
- var require_async_with_await_default = rule$1;
612
+ var require_async_with_await_default = rule$3;
613
+
614
+ //#endregion
615
+ //#region src/utils/sort-imports.ts
616
+ const NEWLINE = /(\r?\n)/;
617
+ const hasNewline = (text) => NEWLINE.test(text);
618
+ function guessNewline(sourceCode) {
619
+ const match = NEWLINE.exec(sourceCode.text);
620
+ return match == null ? "\n" : match[0];
621
+ }
622
+ const withCode = (token, sourceCode) => ({
623
+ ...token,
624
+ code: sourceCode.getText(token)
625
+ });
626
+ function parseWhitespace(whitespace) {
627
+ const allItems = whitespace.split(NEWLINE);
628
+ return (allItems.length >= 5 ? [...allItems.slice(0, 2), ...allItems.slice(-1)] : allItems).map((spacesOrNewline, index) => index % 2 === 0 ? {
629
+ type: "Spaces",
630
+ code: spacesOrNewline
631
+ } : {
632
+ type: "Newline",
633
+ code: spacesOrNewline
634
+ }).filter((token) => token.code !== "");
635
+ }
636
+ const naturalSort = ("default" in natsort ? natsort.default : natsort)();
637
+ function compare(path1, path2) {
638
+ const path1Depth = path1.split("-").filter((p) => p === "__").length;
639
+ const path2Depth = path2.split("-").filter((p) => p === "__").length;
640
+ const path1IsDot = path1 === "_-,";
641
+ const path2IsDot = path2 === "_-,";
642
+ if (path1IsDot && !path2IsDot) return 1;
643
+ if (path2IsDot && !path1IsDot) return -1;
644
+ return path1Depth === path2Depth ? naturalSort(path1, path2) : path2Depth - path1Depth;
645
+ }
646
+ const isIdentifier = (node) => node.type === "Identifier";
647
+ const isKeyword = (node) => node.type === "Keyword";
648
+ const isPunctuator = (node, value) => node.type === "Punctuator" && typeof node.value === "string" && node.value === value;
649
+ const isBlockComment = (node) => node.type === "Block";
650
+ const isLineComment = (node) => node.type === "Line";
651
+ const isSpaces = (node) => node.type === "Spaces";
652
+ const isNewline = (node) => node.type === "Newline";
653
+ const getImportExportKind = (node) => node.importKind ?? node.exportKind ?? "value";
654
+ function getSource(node) {
655
+ const source = String(node.source.value);
656
+ return {
657
+ source: source.replace(/^[./]*\.$/, "$&/").replace(/^[./]*\/$/, "$&,").replace(/[./_-]/g, (char) => {
658
+ switch (char) {
659
+ case ".": return "_";
660
+ case "/": return "-";
661
+ case "_": return ".";
662
+ case "-": return "/";
663
+ default: throw new Error(`Unknown source substitution character: ${char}`);
664
+ }
665
+ }),
666
+ originalSource: source,
667
+ kind: getImportExportKind(node)
668
+ };
669
+ }
670
+ function findLastIndex(array, fn) {
671
+ for (let index = array.length - 1; index >= 0; index--) if (fn(array[index], index, array)) return index;
672
+ return -1;
673
+ }
674
+ const flatMap = (array, fn) => array.flatMap((item, index) => fn(item, index));
675
+ function getAllTokens(node, sourceCode) {
676
+ const tokens = sourceCode.getTokens(node);
677
+ const lastTokenIndex = tokens.length - 1;
678
+ return flatMap(tokens, (token, tokenIndex) => {
679
+ const newToken = withCode(token, sourceCode);
680
+ if (tokenIndex === lastTokenIndex) return [newToken];
681
+ const comments = sourceCode.getCommentsAfter(token);
682
+ const last = comments.length > 0 ? comments[comments.length - 1] : token;
683
+ const nextToken = tokens[tokenIndex + 1];
684
+ return [
685
+ newToken,
686
+ ...flatMap(comments, (comment, commentIndex) => {
687
+ const previous = commentIndex === 0 ? token : comments[commentIndex - 1];
688
+ return [...parseWhitespace(sourceCode.text.slice(previous.range[1], comment.range[0])), withCode(comment, sourceCode)];
689
+ }),
690
+ ...parseWhitespace(sourceCode.text.slice(last.range[1], nextToken.range[0]))
691
+ ];
692
+ });
693
+ }
694
+ const printTokens = (tokens) => tokens.map((token) => token.code).join("");
695
+ const removeBlankLines = (whitespace) => printTokens(parseWhitespace(whitespace));
696
+ function printCommentsBefore(node, comments, sourceCode) {
697
+ const lastIndex = comments.length - 1;
698
+ return comments.map((comment, index) => {
699
+ const next = index === lastIndex ? node : comments[index + 1];
700
+ return sourceCode.getText(comment) + removeBlankLines(sourceCode.text.slice(comment.range[1], next.range[0]));
701
+ }).join("");
702
+ }
703
+ const printCommentsAfter = (node, comments, sourceCode) => comments.map((comment, index) => {
704
+ const previous = index === 0 ? node : comments[index - 1];
705
+ return removeBlankLines(sourceCode.text.slice(previous.range[1], comment.range[0])) + sourceCode.getText(comment);
706
+ }).join("");
707
+ function getIndentationAt(index, sourceCode) {
708
+ const lines = sourceCode.text.slice(0, index).split(NEWLINE);
709
+ return lines[lines.length - 1];
710
+ }
711
+ function getTrailingSpacesAt(index, sourceCode) {
712
+ const { text } = sourceCode;
713
+ let end = index;
714
+ while (end < text.length) {
715
+ const char = text[end];
716
+ if (char === " " || char === " ") {
717
+ end++;
718
+ continue;
719
+ }
720
+ break;
721
+ }
722
+ return text.slice(index, end);
723
+ }
724
+ const sortImportExportItems = (items) => [...items].sort((itemA, itemB) => itemA.isSideEffectImport && itemB.isSideEffectImport ? itemA.index - itemB.index : itemA.isSideEffectImport ? -1 : itemB.isSideEffectImport ? 1 : compare(itemA.source.source, itemB.source.source) || compare(itemA.source.originalSource, itemB.source.originalSource) || compare(itemA.source.kind, itemB.source.kind) || itemA.index - itemB.index);
725
+ const getSpecifierName = (node) => node.type === "Identifier" ? node.name : node.value;
726
+ const getExternalName = (node) => getSpecifierName("imported" in node ? node.imported : node.exported);
727
+ const getLocalName = (node) => getSpecifierName(node.local);
728
+ function compareImportExportKind(kindA, kindB) {
729
+ if (kindA === kindB) return 0;
730
+ return kindA === "type" ? -1 : 1;
731
+ }
732
+ const sortSpecifierItems = (items) => [...items].sort((itemA, itemB) => compareImportExportKind(getImportExportKind(itemA.node), getImportExportKind(itemB.node)) || compare(getExternalName(itemA.node), getExternalName(itemB.node)) || compare(getLocalName(itemA.node), getLocalName(itemB.node)) || itemA.index - itemB.index);
733
+ function extractChunks(parentNode, isPartOfChunk$1) {
734
+ const chunks = [];
735
+ let chunk = [];
736
+ let lastNode;
737
+ for (const node of parentNode.body) {
738
+ const result = isPartOfChunk$1(node, lastNode);
739
+ switch (result) {
740
+ case "PartOfChunk":
741
+ chunk.push(node);
742
+ break;
743
+ case "PartOfNewChunk":
744
+ if (chunk.length > 0) chunks.push(chunk);
745
+ chunk = [node];
746
+ break;
747
+ case "NotPartOfChunk":
748
+ if (chunk.length > 0) {
749
+ chunks.push(chunk);
750
+ chunk = [];
751
+ }
752
+ break;
753
+ default: {
754
+ const _never = result;
755
+ throw new Error(`Unknown chunk result: ${String(_never)}`);
756
+ }
757
+ }
758
+ lastNode = node;
759
+ }
760
+ if (chunk.length > 0) chunks.push(chunk);
761
+ return chunks;
762
+ }
763
+ function maybeReportSorting(context, sorted, start, end) {
764
+ const sourceCode = context.sourceCode;
765
+ if (sourceCode.getText().slice(start, end) !== sorted) context.report({
766
+ messageId: "sort",
767
+ loc: {
768
+ start: sourceCode.getLocFromIndex(start),
769
+ end: sourceCode.getLocFromIndex(end)
770
+ },
771
+ fix: (fixer) => fixer.replaceTextRange([start, end], sorted)
772
+ });
773
+ }
774
+ function printSortedItems(sortedItems, originalItems, sourceCode) {
775
+ const newline = guessNewline(sourceCode);
776
+ const sorted = sortedItems.map((groups) => groups.map((groupItems) => groupItems.map((item) => item.code).join(newline)).join(newline)).join(newline + newline);
777
+ const flattened = flatMap(sortedItems, (groups) => flatMap(groups, (g) => g));
778
+ const lastSortedItem = flattened[flattened.length - 1];
779
+ const lastOriginalItem = originalItems[originalItems.length - 1];
780
+ const nextToken = lastSortedItem.needsNewline ? sourceCode.getTokenAfter(lastOriginalItem.node, {
781
+ includeComments: true,
782
+ filter: (token) => token.type !== "Line" && (token.type !== "Block" || token.loc.end.line !== lastOriginalItem.node.loc.end.line)
783
+ }) : void 0;
784
+ return sorted + (nextToken != null && nextToken.loc.start.line === lastOriginalItem.node.loc.end.line ? newline : "");
785
+ }
786
+ const makeEmptyItem = () => ({
787
+ state: "before",
788
+ before: [],
789
+ after: [],
790
+ specifier: [],
791
+ hadComma: false
792
+ });
793
+ function getSpecifierItems(tokens) {
794
+ const result = {
795
+ before: [],
796
+ after: [],
797
+ items: []
798
+ };
799
+ let current = makeEmptyItem();
800
+ for (const token of tokens) switch (current.state) {
801
+ case "before":
802
+ switch (token.type) {
803
+ case "Newline":
804
+ current.before.push(token);
805
+ if (result.before.length === 0 && result.items.length === 0) {
806
+ result.before = current.before;
807
+ current = makeEmptyItem();
808
+ }
809
+ break;
810
+ case "Spaces":
811
+ case "Block":
812
+ case "Line":
813
+ current.before.push(token);
814
+ break;
815
+ default:
816
+ if (result.before.length === 0 && result.items.length === 0) {
817
+ result.before = current.before;
818
+ current = makeEmptyItem();
819
+ }
820
+ current.state = "specifier";
821
+ current.specifier.push(token);
822
+ }
823
+ break;
824
+ case "specifier":
825
+ switch (token.type) {
826
+ case "Punctuator":
827
+ if (isPunctuator(token, ",")) {
828
+ current.hadComma = true;
829
+ current.state = "after";
830
+ } else current.specifier.push(token);
831
+ break;
832
+ default: current.specifier.push(token);
833
+ }
834
+ break;
835
+ case "after":
836
+ switch (token.type) {
837
+ case "Newline":
838
+ current.after.push(token);
839
+ result.items.push(current);
840
+ current = makeEmptyItem();
841
+ break;
842
+ case "Spaces":
843
+ case "Line":
844
+ current.after.push(token);
845
+ break;
846
+ case "Block":
847
+ if (hasNewline(token.code)) {
848
+ result.items.push(current);
849
+ current = makeEmptyItem();
850
+ current.before.push(token);
851
+ } else current.after.push(token);
852
+ break;
853
+ default:
854
+ result.items.push(current);
855
+ current = makeEmptyItem();
856
+ current.state = "specifier";
857
+ current.specifier.push(token);
858
+ }
859
+ break;
860
+ default: {
861
+ const _never = current.state;
862
+ throw new Error(`Unknown state: ${String(_never)}`);
863
+ }
864
+ }
865
+ switch (current.state) {
866
+ case "before":
867
+ result.after = current.before;
868
+ break;
869
+ case "specifier": {
870
+ const lastIdentifierIndex = findLastIndex(current.specifier, (t) => isIdentifier(t) || isKeyword(t));
871
+ const specifier = current.specifier.slice(0, lastIdentifierIndex + 1);
872
+ const after = current.specifier.slice(lastIdentifierIndex + 1);
873
+ const newlineIndexRaw = after.findIndex((t) => isNewline(t));
874
+ const newlineIndex = newlineIndexRaw === -1 ? -1 : newlineIndexRaw + 1;
875
+ const multilineBlockCommentIndex = after.findIndex((t) => isBlockComment(t) && hasNewline(t.code));
876
+ const sliceIndex = newlineIndex >= 0 && multilineBlockCommentIndex !== -1 ? Math.min(newlineIndex, multilineBlockCommentIndex) : newlineIndex >= 0 ? newlineIndex : multilineBlockCommentIndex === -1 ? endsWithSpaces(after) ? after.length - 1 : -1 : multilineBlockCommentIndex;
877
+ current.specifier = specifier;
878
+ current.after = sliceIndex === -1 ? after : after.slice(0, sliceIndex);
879
+ result.items.push(current);
880
+ result.after = sliceIndex === -1 ? [] : after.slice(sliceIndex);
881
+ break;
882
+ }
883
+ case "after":
884
+ if (endsWithSpaces(current.after)) {
885
+ const last = current.after.pop();
886
+ if (last) result.after = [last];
887
+ }
888
+ result.items.push(current);
889
+ break;
890
+ default: {
891
+ const _never = current.state;
892
+ throw new Error(`Unknown state: ${String(_never)}`);
893
+ }
894
+ }
895
+ return {
896
+ before: result.before,
897
+ after: result.after,
898
+ items: result.items.map((item) => ({
899
+ before: item.before,
900
+ after: item.after,
901
+ specifier: item.specifier,
902
+ hadComma: item.hadComma
903
+ }))
904
+ };
905
+ }
906
+ function needsStartingNewline(tokens) {
907
+ const before = tokens.filter((token) => !isSpaces(token));
908
+ if (before.length === 0) return false;
909
+ const firstToken = before[0];
910
+ return isLineComment(firstToken) || isBlockComment(firstToken) && !hasNewline(firstToken.code);
911
+ }
912
+ function endsWithSpaces(tokens) {
913
+ const last = tokens.length > 0 ? tokens[tokens.length - 1] : void 0;
914
+ return last == null ? false : isSpaces(last);
915
+ }
916
+ function printWithSortedSpecifiers(node, sourceCode, getSpecifiers$2) {
917
+ const allTokens = getAllTokens(node, sourceCode);
918
+ const openBraceIndex = allTokens.findIndex((token) => isPunctuator(token, "{"));
919
+ const closeBraceIndex = allTokens.findIndex((token) => isPunctuator(token, "}"));
920
+ const specifiers = getSpecifiers$2(node);
921
+ if (openBraceIndex === -1 || closeBraceIndex === -1 || specifiers.length <= 1) return printTokens(allTokens);
922
+ const itemsResult = getSpecifierItems(allTokens.slice(openBraceIndex + 1, closeBraceIndex));
923
+ const sortedItems = sortSpecifierItems(itemsResult.items.map((originalItem, index) => ({
924
+ ...originalItem,
925
+ node: specifiers[index],
926
+ index
927
+ })));
928
+ const newline = guessNewline(sourceCode);
929
+ const hasTrailingComma = (() => {
930
+ for (let index = closeBraceIndex - 1; index > openBraceIndex; index--) {
931
+ const token = allTokens[index];
932
+ if (token.type === "Spaces" || token.type === "Newline" || token.type === "Block" || token.type === "Line") continue;
933
+ return isPunctuator(token, ",");
934
+ }
935
+ return false;
936
+ })();
937
+ const lastIndex = sortedItems.length - 1;
938
+ const sorted = flatMap(sortedItems, (item, index) => {
939
+ const previous = index === 0 ? void 0 : sortedItems[index - 1];
940
+ const maybeNewline$1 = previous != null && needsStartingNewline(item.before) && (previous.after.length <= 0 || !isNewline(previous.after[previous.after.length - 1])) ? [{
941
+ type: "Newline",
942
+ code: newline
943
+ }] : [];
944
+ if (index < lastIndex || hasTrailingComma) return [
945
+ ...maybeNewline$1,
946
+ ...item.before,
947
+ ...item.specifier,
948
+ {
949
+ type: "Comma",
950
+ code: ","
951
+ },
952
+ ...item.after
953
+ ];
954
+ const nonBlankIndex = item.after.findIndex((token) => !isNewline(token) && !isSpaces(token));
955
+ const after = item.hadComma ? nonBlankIndex === -1 ? [] : item.after.slice(nonBlankIndex) : item.after;
956
+ return [
957
+ ...maybeNewline$1,
958
+ ...item.before,
959
+ ...item.specifier,
960
+ ...after
961
+ ];
962
+ });
963
+ const maybeNewline = needsStartingNewline(itemsResult.after) && !isNewline(sorted[sorted.length - 1]) ? [{
964
+ type: "Newline",
965
+ code: newline
966
+ }] : [];
967
+ return printTokens([
968
+ ...allTokens.slice(0, openBraceIndex + 1),
969
+ ...itemsResult.before,
970
+ ...sorted,
971
+ ...maybeNewline,
972
+ ...itemsResult.after,
973
+ ...allTokens.slice(closeBraceIndex)
974
+ ]);
975
+ }
976
+ function handleLastSemicolon(chunk, sourceCode) {
977
+ const lastIndex = chunk.length - 1;
978
+ const lastNode = chunk[lastIndex];
979
+ const tokens = sourceCode.getLastTokens(lastNode, { count: 2 });
980
+ if (tokens.length < 2) return [...chunk];
981
+ const [nextToLastToken, lastToken] = tokens;
982
+ if (!(lastToken.type === "Punctuator" && lastToken.value === ";")) return [...chunk];
983
+ if (nextToLastToken.loc.end.line === lastToken.loc.start.line || sourceCode.getTokenAfter(lastToken) == null) return [...chunk];
984
+ const newLastNode = {
985
+ ...lastNode,
986
+ range: [lastNode.range[0], nextToLastToken.range[1]],
987
+ loc: {
988
+ start: lastNode.loc.start,
989
+ end: nextToLastToken.loc.end
990
+ }
991
+ };
992
+ return [...chunk.slice(0, lastIndex), newLastNode];
993
+ }
994
+ function getImportExportItems(passedChunk, sourceCode, isSideEffectImport$1, getSpecifiers$2) {
995
+ const chunk = handleLastSemicolon(passedChunk, sourceCode);
996
+ return chunk.map((node, nodeIndex) => {
997
+ const lastLine = nodeIndex === 0 ? node.loc.start.line - 1 : chunk[nodeIndex - 1].loc.end.line;
998
+ const commentsBefore = sourceCode.getCommentsBefore(node).filter((comment) => comment.loc.start.line <= node.loc.start.line && comment.loc.end.line > lastLine && (nodeIndex > 0 || comment.loc.start.line > lastLine));
999
+ const commentsAfter = sourceCode.getCommentsAfter(node).filter((comment) => comment.loc.end.line === node.loc.end.line);
1000
+ const before = printCommentsBefore(node, commentsBefore, sourceCode);
1001
+ const after = printCommentsAfter(node, commentsAfter, sourceCode);
1002
+ const indentation = getIndentationAt((commentsBefore.length > 0 ? commentsBefore[0] : node).range[0], sourceCode);
1003
+ const trailingSpaces = getTrailingSpacesAt((commentsAfter.length > 0 ? commentsAfter[commentsAfter.length - 1] : node).range[1], sourceCode);
1004
+ const code = indentation + before + printWithSortedSpecifiers(node, sourceCode, getSpecifiers$2) + after + trailingSpaces;
1005
+ const all = [
1006
+ ...commentsBefore,
1007
+ node,
1008
+ ...commentsAfter
1009
+ ];
1010
+ const [start] = all[0].range;
1011
+ const [, end] = all[all.length - 1].range;
1012
+ const source = getSource(node);
1013
+ const lastAfter = commentsAfter.length > 0 ? commentsAfter[commentsAfter.length - 1] : void 0;
1014
+ return {
1015
+ node,
1016
+ code,
1017
+ start: start - indentation.length,
1018
+ end: end + trailingSpaces.length,
1019
+ isSideEffectImport: isSideEffectImport$1(node, sourceCode),
1020
+ source,
1021
+ index: nodeIndex,
1022
+ needsNewline: lastAfter?.type === "Line"
1023
+ };
1024
+ });
1025
+ }
1026
+
1027
+ //#endregion
1028
+ //#region src/rules/sort-exports.ts
1029
+ const RULE_NAME$2 = "sort-exports";
1030
+ function isParentWithBody$1(node) {
1031
+ if (!node) return false;
1032
+ if (!("body" in node)) return false;
1033
+ const maybe = node;
1034
+ return Array.isArray(maybe.body);
1035
+ }
1036
+ const isExportFrom = (node) => node.type === "ExportNamedDeclaration" && node.source != null || node.type === "ExportAllDeclaration" && node.source != null;
1037
+ function isPartOfChunk(node, lastNode, sourceCode) {
1038
+ if (!isExportFrom(node)) return "NotPartOfChunk";
1039
+ return sourceCode.getCommentsBefore(node).some((comment) => (lastNode == null || comment.loc.start.line > lastNode.loc.end.line) && comment.loc.end.line < node.loc.start.line) ? "PartOfNewChunk" : "PartOfChunk";
1040
+ }
1041
+ const getSpecifiers$1 = (exportNode) => exportNode.type === "ExportNamedDeclaration" ? exportNode.specifiers : [];
1042
+ function maybeReportChunkSorting$1(chunk, context) {
1043
+ const sourceCode = context.sourceCode;
1044
+ const items = getImportExportItems(chunk.filter(isExportFrom), sourceCode, () => false, getSpecifiers$1);
1045
+ const sorted = printSortedItems([[sortImportExportItems(items)]], items, sourceCode);
1046
+ const start = items[0].start;
1047
+ const end = items[items.length - 1].end;
1048
+ maybeReportSorting(context, sorted, start, end);
1049
+ }
1050
+ function maybeReportExportSpecifierSorting(node, context) {
1051
+ const sorted = printWithSortedSpecifiers(node, context.sourceCode, (n) => n.specifiers);
1052
+ const [start, end] = node.range;
1053
+ maybeReportSorting(context, sorted, start, end);
1054
+ }
1055
+ const rule$2 = createEslintRule({
1056
+ name: RULE_NAME$2,
1057
+ meta: {
1058
+ type: "layout",
1059
+ docs: {
1060
+ description: "Sort export declarations.",
1061
+ url: "https://github.com/lydell/eslint-plugin-simple-import-sort#sort-order"
1062
+ },
1063
+ fixable: "code",
1064
+ schema: [],
1065
+ messages: { sort: "Run autofix to sort these exports!" }
1066
+ },
1067
+ defaultOptions: [],
1068
+ create: (context) => {
1069
+ const parents = /* @__PURE__ */ new Set();
1070
+ function addParent(node) {
1071
+ if (isExportFrom(node) && isParentWithBody$1(node.parent)) parents.add(node.parent);
1072
+ }
1073
+ return {
1074
+ ExportNamedDeclaration(node) {
1075
+ if (node.source == null && node.declaration == null) maybeReportExportSpecifierSorting(node, context);
1076
+ else addParent(node);
1077
+ },
1078
+ ExportAllDeclaration(node) {
1079
+ addParent(node);
1080
+ },
1081
+ "Program:exit"() {
1082
+ const sourceCode = context.sourceCode;
1083
+ for (const parent of parents) for (const chunk of extractChunks(parent, (node, lastNode) => isPartOfChunk(node, lastNode, sourceCode))) maybeReportChunkSorting$1(chunk, context);
1084
+ parents.clear();
1085
+ }
1086
+ };
1087
+ }
1088
+ });
1089
+ var sort_exports_default = rule$2;
1090
+
1091
+ //#endregion
1092
+ //#region src/rules/sort-imports.ts
1093
+ const RULE_NAME$1 = "sort-imports";
1094
+ function isParentWithBody(node) {
1095
+ if (!node) return false;
1096
+ if (!("body" in node)) return false;
1097
+ const maybe = node;
1098
+ return Array.isArray(maybe.body);
1099
+ }
1100
+ const defaultGroups = [
1101
+ ["^node:"],
1102
+ ["^@?\\w"],
1103
+ ["^"],
1104
+ ["^\\."],
1105
+ ["^\\u0000"]
1106
+ ];
1107
+ const isImportSpecifier = (node) => node.type === "ImportSpecifier";
1108
+ const getSpecifiers = (importNode) => importNode.specifiers.filter(isImportSpecifier);
1109
+ const isImport = (node) => node.type === "ImportDeclaration";
1110
+ function isSideEffectImport(importNode, sourceCode) {
1111
+ const token = sourceCode.getFirstToken(importNode, { skip: 1 });
1112
+ const startsWithBrace = token != null && isPunctuator(token, "{");
1113
+ return importNode.specifiers.length === 0 && (!importNode.importKind || importNode.importKind === "value") && !startsWithBrace;
1114
+ }
1115
+ const rule$1 = createEslintRule({
1116
+ name: RULE_NAME$1,
1117
+ meta: {
1118
+ type: "layout",
1119
+ docs: {
1120
+ description: "Sort import declarations.",
1121
+ url: "https://github.com/lydell/eslint-plugin-simple-import-sort#sort-order"
1122
+ },
1123
+ fixable: "code",
1124
+ schema: [{
1125
+ type: "object",
1126
+ properties: { groups: {
1127
+ type: "array",
1128
+ items: {
1129
+ type: "array",
1130
+ items: { type: "string" }
1131
+ }
1132
+ } },
1133
+ additionalProperties: false
1134
+ }],
1135
+ messages: { sort: "Run autofix to sort these imports!" }
1136
+ },
1137
+ defaultOptions: [{ groups: defaultGroups }],
1138
+ create: (context) => {
1139
+ const outerGroups = (context.options[0]?.groups ?? defaultGroups).map((groups) => groups.map((item) => new RegExp(item, "u")));
1140
+ const parents = /* @__PURE__ */ new Set();
1141
+ return {
1142
+ ImportDeclaration(node) {
1143
+ if (isParentWithBody(node.parent)) parents.add(node.parent);
1144
+ },
1145
+ "Program:exit"() {
1146
+ const sourceCode = context.sourceCode;
1147
+ for (const parent of parents) for (const chunk of extractChunks(parent, (node) => isImport(node) ? "PartOfChunk" : "NotPartOfChunk")) maybeReportChunkSorting(chunk, context, outerGroups, sourceCode);
1148
+ parents.clear();
1149
+ }
1150
+ };
1151
+ }
1152
+ });
1153
+ var sort_imports_default = rule$1;
1154
+ function maybeReportChunkSorting(chunk, context, outerGroups, sourceCode) {
1155
+ const items = getImportExportItems(chunk.filter(isImport), sourceCode, isSideEffectImport, getSpecifiers);
1156
+ const sorted = printSortedItems(makeSortedItems(items, outerGroups), items, sourceCode);
1157
+ const start = items[0].start;
1158
+ const end = items[items.length - 1].end;
1159
+ maybeReportSorting(context, sorted, start, end);
1160
+ }
1161
+ function makeSortedItems(items, outerGroups) {
1162
+ const itemGroups = outerGroups.map((groups) => groups.map((regex) => ({
1163
+ regex,
1164
+ items: []
1165
+ })));
1166
+ const rest = [];
1167
+ for (const item of items) {
1168
+ const { originalSource } = item.source;
1169
+ const source = item.isSideEffectImport ? `\0${originalSource}` : item.source.kind === "value" ? originalSource : `${originalSource}\0`;
1170
+ let matchedGroup;
1171
+ let longestMatchLength = -1;
1172
+ for (const groups of itemGroups) for (const group of groups) {
1173
+ const match = group.regex.exec(source);
1174
+ if (match != null && match[0].length > longestMatchLength) {
1175
+ matchedGroup = group;
1176
+ longestMatchLength = match[0].length;
1177
+ }
1178
+ }
1179
+ if (matchedGroup == null) rest.push(item);
1180
+ else matchedGroup.items.push(item);
1181
+ }
1182
+ return [...itemGroups, [{
1183
+ regex: /^/,
1184
+ items: rest
1185
+ }]].map((groups) => groups.filter((group) => group.items.length > 0)).filter((groups) => groups.length > 0).map((groups) => groups.map((group) => sortImportExportItems(group.items)));
1186
+ }
593
1187
 
594
1188
  //#endregion
595
1189
  //#region src/rules/vue-root-element-sort-attributes.ts
@@ -662,11 +1256,13 @@ var src_default = { rules: {
662
1256
  "import-dedupe": import_dedupe_default,
663
1257
  "import-export-newline": import_export_newline_default,
664
1258
  "no-import-promises-as": no_import_promises_as_default,
665
- "no-inline-type-import": no_inline_type_import_default,
1259
+ "no-inline-type-modifier": no_inline_type_modifier_default,
666
1260
  "no-negated-comparison": no_negated_comparison_default,
667
1261
  "no-useless-template-string": no_useless_template_string_default,
668
1262
  "prefer-ts-expect-error": prefer_ts_expect_error_default,
669
1263
  "require-async-with-await": require_async_with_await_default,
1264
+ "sort-exports": sort_exports_default,
1265
+ "sort-imports": sort_imports_default,
670
1266
  "vue-root-element-sort-attributes": vue_root_element_sort_attributes_default
671
1267
  } };
672
1268
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@so1ve/eslint-plugin",
3
- "version": "4.0.1",
3
+ "version": "4.1.0",
4
4
  "author": "Ray <i@mk1.io> (https://github.com/so1ve/)",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -32,7 +32,8 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@typescript-eslint/types": "^8.50.1",
35
- "@typescript-eslint/utils": "^8.50.1"
35
+ "@typescript-eslint/utils": "^8.50.1",
36
+ "natsort": "^2.0.3"
36
37
  },
37
38
  "devDependencies": {
38
39
  "@html-eslint/parser": "^0.52.0",