@aiou/eslint-config 3.1.1 → 3.1.2

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 CHANGED
@@ -10,7 +10,7 @@ Flat ESLint config with TypeScript, React, SSR, and more.
10
10
  - TypeScript, YAML, JSONC, Markdown, TOML support
11
11
  - Built-in React rules via `@eslint-react`, react-refresh, and SSR-safe linting
12
12
  - Auto-detected framework support (Next.js, Tailwind CSS)
13
- - Import sorting, unused import removal, and multi-line import enforcement
13
+ - Import sorting and unused import removal via `eslint-plugin-perfectionist`
14
14
  - Sorted keys for `package.json` and `tsconfig.json`
15
15
  - Visual linting progress reporter
16
16
 
@@ -96,7 +96,7 @@ The following plugins are enabled automatically when their packages are found in
96
96
  | Arrow parens | `as-needed` |
97
97
  | Curly | `all` |
98
98
  | File naming | `kebab-case` (via unicorn) |
99
- | Import sorting | side-effects`node:` builtins → packages → relative/aliasvirtual types |
99
+ | Import sorting | type-imports → builtins/externalsinternal → relative → side-effects (via `perfectionist`) |
100
100
 
101
101
  ## Included Plugins
102
102
 
@@ -108,8 +108,7 @@ The following plugins are enabled automatically when their packages are found in
108
108
  | `eslint-plugin-react-refresh` | React Refresh compatibility |
109
109
  | `@stylistic/eslint-plugin` | Formatting rules |
110
110
  | `eslint-plugin-import-x` | Import rules |
111
- | `eslint-plugin-simple-import-sort` | Import sorting |
112
- | `eslint-plugin-import-newlines` | Multi-line import enforcement |
111
+ | `eslint-plugin-perfectionist` | Import sorting, type sorting (union/intersection/named imports) |
113
112
  | `eslint-plugin-unused-imports` | Unused import/variable removal |
114
113
  | `eslint-plugin-unicorn` | Best practice rules |
115
114
  | `eslint-plugin-n` | Node.js rules |
package/dist/index.mjs CHANGED
@@ -2,9 +2,7 @@ import { FlatConfigComposer } from 'eslint-flat-config-utils';
2
2
  import { isPackageExists } from 'local-pkg';
3
3
  import pluginComments from '@eslint-community/eslint-plugin-eslint-comments';
4
4
  import ignoreGlobs from '@aiou/eslint-ignore';
5
- import pluginImportNewlines from 'eslint-plugin-import-newlines';
6
5
  import pluginImport from 'eslint-plugin-import-x';
7
- import pluginSimpleImportSort from 'eslint-plugin-simple-import-sort';
8
6
  import pluginUnsedImports from 'eslint-plugin-unused-imports';
9
7
  import pluginN from 'eslint-plugin-n';
10
8
  import pluginPromise from 'eslint-plugin-promise';
@@ -12,6 +10,7 @@ import globals from 'globals';
12
10
  import pluginJsonc from 'eslint-plugin-jsonc';
13
11
  import pluginMarkdown from '@eslint/markdown';
14
12
  import pluginNext from '@next/eslint-plugin-next';
13
+ import pluginPerfectionist from 'eslint-plugin-perfectionist';
15
14
  import pluginProgress from '@aiou/eslint-plugin-progress';
16
15
  import pluginReact from '@eslint-react/eslint-plugin';
17
16
  import pluginReactHooks from 'eslint-plugin-react-hooks';
@@ -76,8 +75,6 @@ const imports = () => {
76
75
  {
77
76
  plugins: {
78
77
  import: pluginImport,
79
- "simple-import-sort": pluginSimpleImportSort,
80
- "import-newlines": pluginImportNewlines,
81
78
  "unused-imports": pluginUnsedImports
82
79
  },
83
80
  rules: {
@@ -85,29 +82,6 @@ const imports = () => {
85
82
  // off: controlled by import/order
86
83
  "import/order": "off",
87
84
  "sort-imports": "off",
88
- "simple-import-sort/imports": [
89
- "warn",
90
- {
91
- groups: [
92
- // Side effect imports.
93
- [String.raw`^\u0000`],
94
- // Node.js builtins prefixed with `node:`.
95
- ["^node:"],
96
- // Packages.
97
- // Things that start with a letter (or digit or underscore), or `@` followed by a letter.
98
- [String.raw`^@?\w`],
99
- // Relative imports.
100
- // Absolute imports and other imports such as `@/foo` or `~/foo`.
101
- // Anything not matched in another group.
102
- ["^", String.raw`^\.`, String.raw`^@/\w`, String.raw`^~/\w`],
103
- // Virtual modules prefixed with `virtual:` or `virtual-`, rollup & vite favor
104
- ["^virtual:", "^virtual-"],
105
- // Types
106
- ["^[^/\\.].*\0$", "^\\..*\0$"]
107
- ]
108
- }
109
- ],
110
- "simple-import-sort/exports": "off",
111
85
  "import/first": "error",
112
86
  "import/newline-after-import": "error",
113
87
  "import/no-duplicates": "error",
@@ -133,15 +107,6 @@ const imports = () => {
133
107
  args: "after-used",
134
108
  argsIgnorePattern: "^_"
135
109
  }
136
- ],
137
- // Enforce newlines inside named import
138
- "import-newlines/enforce": [
139
- "error",
140
- {
141
- items: 2,
142
- "max-len": 120,
143
- semi: false
144
- }
145
110
  ]
146
111
  }
147
112
  },
@@ -753,7 +718,8 @@ const markdown = () => {
753
718
  "import/no-anonymous-default-export": "off",
754
719
  "react-refresh/only-export-components": "off",
755
720
  "react/jsx-no-undef": "off",
756
- "unicorn/filename-case": "off"
721
+ "unicorn/filename-case": "off",
722
+ "perfectionist/sort-imports": "off"
757
723
  }
758
724
  }
759
725
  ];
@@ -775,6 +741,46 @@ const next = () => {
775
741
  return config;
776
742
  };
777
743
 
744
+ const perfectionist = () => {
745
+ return [
746
+ {
747
+ plugins: {
748
+ perfectionist: pluginPerfectionist
749
+ },
750
+ rules: {
751
+ "perfectionist/sort-imports": [
752
+ "warn",
753
+ {
754
+ type: "natural",
755
+ order: "asc",
756
+ newlinesBetween: "ignore",
757
+ groups: [
758
+ "type-import",
759
+ ["value-builtin", "value-external"],
760
+ "type-internal",
761
+ "value-internal",
762
+ ["type-parent", "type-sibling", "type-index"],
763
+ ["value-parent", "value-sibling", "value-index"],
764
+ "side-effect",
765
+ "unknown"
766
+ ],
767
+ customGroups: [
768
+ {
769
+ groupName: "virtual-modules",
770
+ elementNamePattern: ["^virtual:", "^virtual-"]
771
+ }
772
+ ],
773
+ internalPattern: ["^~/.+", "^@/.+", "^#.+"]
774
+ }
775
+ ],
776
+ "perfectionist/sort-union-types": ["error", { type: "natural", order: "asc" }],
777
+ "perfectionist/sort-intersection-types": ["error", { type: "natural", order: "asc" }],
778
+ "perfectionist/sort-named-imports": ["warn", { type: "natural", order: "asc" }]
779
+ }
780
+ }
781
+ ];
782
+ };
783
+
778
784
  const progress = () => {
779
785
  const config = [
780
786
  {
@@ -823,33 +829,28 @@ const react = () => {
823
829
  react: pluginReact,
824
830
  "react-dom": pluginReact,
825
831
  "react-hooks": pluginReactHooks,
826
- "react-hooks-extra": pluginReact,
827
832
  "react-naming-convention": pluginReact,
828
833
  "react-refresh": pluginReactRefresh,
829
834
  "react-web-api": pluginReact
830
835
  },
831
836
  rules: {
832
837
  ...renameRules(pluginReact.configs["recommended-typescript"].rules, { "@eslint-react": "react" }),
833
- ...renameRules(pluginReact.configs.dom.rules, { "@eslint-react": "react-dom" }),
834
- ...renameRules(pluginReact.configs.x.rules, { "@eslint-react": "react-hooks-extra" }),
835
- ...renameRules(pluginReact.configs.x.rules, { "@eslint-react": "react-naming-convention" }),
836
- ...renameRules(pluginReact.configs["web-api"].rules, { "@eslint-react": "react-web-api" }),
837
838
  ...pluginReactHooks.configs.flat.recommended.rules,
838
839
  "react/no-nested-component-definitions": "warn",
839
- "react-dom/no-unknown-property": "off",
840
+ "react-dom/dom-no-unknown-property": "off",
840
841
  "react-refresh/only-export-components": "warn"
841
842
  }
842
843
  },
843
844
  {
844
845
  files: ["src/components/**/*.{ts,tsx}"],
845
846
  rules: {
846
- "react-naming-convention/filename": ["warn", { rule: "PascalCase" }]
847
+ "unicorn/filename-case": ["warn", { case: "pascalCase" }]
847
848
  }
848
849
  },
849
850
  {
850
851
  files: ["src/hooks/**/use*.{ts,tsx}"],
851
852
  rules: {
852
- "react-naming-convention/filename": ["warn", { rule: "kebab-case" }]
853
+ "unicorn/filename-case": ["warn", { case: "kebabCase" }]
853
854
  }
854
855
  },
855
856
  {
@@ -1180,10 +1181,7 @@ const typescript = () => {
1180
1181
  ],
1181
1182
  // Limit `interface` define object types, users could override with *.d.ts declare
1182
1183
  "@typescript-eslint/consistent-type-definitions": ["error", "interface"],
1183
- "@typescript-eslint/prefer-ts-expect-error": "warn",
1184
1184
  "@typescript-eslint/default-param-last": "error",
1185
- // Sort type S = A | B
1186
- "@typescript-eslint/sort-type-constituents": "error",
1187
1185
  "@typescript-eslint/unbound-method": "off",
1188
1186
  "@typescript-eslint/prefer-for-of": "error",
1189
1187
  // When .ts files compiled to .mjs, will throw require is not found
@@ -1227,8 +1225,7 @@ const typescript = () => {
1227
1225
  "error",
1228
1226
  { functions: false, classes: false, variables: true }
1229
1227
  ],
1230
- "no-loss-of-precision": "off",
1231
- "@typescript-eslint/no-loss-of-precision": "error",
1228
+ "no-loss-of-precision": "error",
1232
1229
  "no-unused-expressions": "off",
1233
1230
  "@typescript-eslint/no-unused-expressions": ["error", {
1234
1231
  allowShortCircuit: true,
@@ -1236,19 +1233,13 @@ const typescript = () => {
1236
1233
  allowTaggedTemplates: true
1237
1234
  }],
1238
1235
  // off
1239
- "@typescript-eslint/camelcase": "off",
1240
1236
  "@typescript-eslint/explicit-function-return-type": "off",
1241
1237
  "@typescript-eslint/explicit-member-accessibility": "off",
1242
1238
  "@typescript-eslint/no-explicit-any": "off",
1243
- "@typescript-eslint/no-parameter-properties": "off",
1244
- "@typescript-eslint/no-empty-interface": "off",
1245
- "@typescript-eslint/ban-ts-ignore": "off",
1246
1239
  "@typescript-eslint/no-empty-function": "off",
1247
1240
  "@typescript-eslint/no-non-null-assertion": "off",
1248
1241
  "@typescript-eslint/explicit-module-boundary-types": "off",
1249
- "@typescript-eslint/ban-types": "off",
1250
1242
  "@typescript-eslint/no-namespace": "off",
1251
- "@typescript-eslint/no-var-requires": "off",
1252
1243
  // https://www.npmjs.com/package/eslint-plugin-unused-imports
1253
1244
  "@typescript-eslint/no-unused-vars": "off",
1254
1245
  "no-void": ["error", { allowAsStatement: true }],
@@ -1328,7 +1319,8 @@ const presetJavascript = [
1328
1319
  ...javascript(),
1329
1320
  ...comments(),
1330
1321
  ...imports(),
1331
- ...unicorn()
1322
+ ...unicorn(),
1323
+ ...perfectionist()
1332
1324
  ];
1333
1325
  const presetTypescript = [
1334
1326
  ...presetJavascript,
@@ -1354,9 +1346,9 @@ const all = [
1354
1346
  ...ssrReact(),
1355
1347
  ...regexp()
1356
1348
  ];
1357
- const aiou = ({ ssr = true, regexp: regexp$1 = true } = { ssr: true, regexp: true }, ...userConfigs) => {
1349
+ const aiou = ({ ssr = true, regexp: regexp$1 = true, tailwindcss: enableTailwindcss = true } = {}, ...userConfigs) => {
1358
1350
  const configs = [...presetDefault];
1359
- if (isPackageExists("tailwindcss")) {
1351
+ if (enableTailwindcss && isPackageExists("tailwindcss")) {
1360
1352
  configs.push(...tailwindcss());
1361
1353
  }
1362
1354
  if (isPackageExists("next")) {
@@ -0,0 +1,2 @@
1
+ import type { Config } from '../type';
2
+ export declare const perfectionist: () => Config[];
package/dts/index.d.ts CHANGED
@@ -1,12 +1,13 @@
1
- import { FlatConfigComposer } from 'eslint-flat-config-utils';
2
1
  import type { Linter } from 'eslint';
3
2
  import type { Arrayable, Awaitable } from 'eslint-flat-config-utils';
3
+ import { FlatConfigComposer } from 'eslint-flat-config-utils';
4
4
  import type { Config } from './type';
5
5
  import type { ConfigNames } from './typegen';
6
6
  export declare const all: Config[];
7
7
  interface Options {
8
8
  ssr?: boolean;
9
9
  regexp?: boolean;
10
+ tailwindcss?: boolean;
10
11
  }
11
- export declare const aiou: ({ ssr, regexp }?: Options, ...userConfigs: Awaitable<Arrayable<Config> | FlatConfigComposer<any, any> | Linter.Config[]>[]) => FlatConfigComposer<Config, ConfigNames>;
12
+ export declare const aiou: ({ ssr, regexp, tailwindcss: enableTailwindcss }?: Options, ...userConfigs: Awaitable<Arrayable<Config> | FlatConfigComposer<any, any> | Linter.Config[]>[]) => FlatConfigComposer<Config, ConfigNames>;
12
13
  export {};