diff --git a/.eslintrc.js b/.eslintrc.js index 4a22b6e..b412e79 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,6 +1,6 @@ module.exports = { root: true, - plugins: ['unicorn', 'jsdoc'], + plugins: ['unicorn', 'jsdoc', 'import-x'], env: { node: true, browser: true, es2023: true }, reportUnusedDisableDirectives: true, parserOptions: { @@ -14,7 +14,6 @@ module.exports = { 'plugin:@typescript-eslint/recommended-type-checked', 'plugin:jsdoc/recommended-typescript', ], - overrides: [ { files: ['repl.ts', 'scripts/**/*.ts'], @@ -31,6 +30,22 @@ module.exports = { }, ], rules: { + 'import-x/order': [ + 'error', + { + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + 'object', + ], + 'newlines-between': 'always-and-inside-groups', + alphabetize: { order: 'asc', caseInsensitive: true }, + }, + ], 'arrow-body-style': ['error', 'as-needed'], 'class-methods-use-this': 'warn', 'func-style': ['error', 'declaration', { allowArrowFunctions: true }], diff --git a/dist/package.json b/dist/package.json index 37e43de..54eb6fc 100644 --- a/dist/package.json +++ b/dist/package.json @@ -1,6 +1,6 @@ { "name": "@aet/eslint-rules", - "version": "1.0.1-beta.25", + "version": "1.0.1-beta.28", "license": "UNLICENSED", "bin": { "eslint-install": "install.js", @@ -11,16 +11,16 @@ "typescript": "^5.4.4" }, "dependencies": { - "@antfu/install-pkg": "^0.3.3", + "@antfu/install-pkg": "^0.3.4", "@nolyfill/is-core-module": "^1.0.39", - "@aet/eslint-define-config": "^0.1.0-beta.21", + "@aet/eslint-define-config": "^0.1.0-beta.22", "@eslint-community/eslint-utils": "^4.4.0", "@tanstack/eslint-plugin-query": "^5.51.15", "@types/eslint": "^9.6.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "@typescript-eslint/type-utils": "^7.18.0", - "@typescript-eslint/utils": "^7.18.0", + "@typescript-eslint/eslint-plugin": "^8.1.0", + "@typescript-eslint/parser": "^8.1.0", + "@typescript-eslint/type-utils": "^8.1.0", + "@typescript-eslint/utils": "^8.1.0", "@eslint-react/eslint-plugin": "1.10.0", "@stylistic/eslint-plugin": "^2.6.2", "aria-query": "^5.3.0", diff --git a/package.json b/package.json index 1b4529a..a8f2de3 100644 --- a/package.json +++ b/package.json @@ -8,8 +8,8 @@ }, "private": true, "devDependencies": { - "@aet/eslint-define-config": "^0.1.0-beta.21", - "@antfu/install-pkg": "^0.3.3", + "@aet/eslint-define-config": "^0.1.0-beta.22", + "@antfu/install-pkg": "^0.3.4", "@babel/core": "^7.25.2", "@babel/plugin-transform-flow-strip-types": "^7.25.2", "@babel/preset-env": "^7.25.3", @@ -22,11 +22,11 @@ "@types/estree-jsx": "^1.0.5", "@types/lodash": "^4.17.7", "@types/node": "^22.2.0", - "@typescript-eslint/eslint-plugin": "^8.0.1", - "@typescript-eslint/type-utils": "^8.0.1", - "@typescript-eslint/types": "^8.0.1", - "@typescript-eslint/typescript-estree": "^8.0.1", - "@typescript-eslint/utils": "^8.0.1", + "@typescript-eslint/eslint-plugin": "^8.1.0", + "@typescript-eslint/type-utils": "^8.1.0", + "@typescript-eslint/types": "^8.1.0", + "@typescript-eslint/typescript-estree": "^8.1.0", + "@typescript-eslint/utils": "^8.1.0", "babel-plugin-macros": "^3.1.0", "dts-bundle-generator": "9.4.0", "esbuild": "0.23.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 49f1b96..b97a6f9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,8 +28,8 @@ importers: .: devDependencies: '@aet/eslint-define-config': - specifier: ^0.1.0-beta.18 - version: 0.1.0-beta.18 + specifier: ^0.1.0-beta.22 + version: 0.1.0-beta.22 '@antfu/install-pkg': specifier: ^0.3.3 version: 0.3.3 @@ -156,8 +156,8 @@ importers: packages: - '@aet/eslint-define-config@0.1.0-beta.18': - resolution: {integrity: sha512-s5BWjeE78j8cNvIfjztTGsvRM03Asx9wG62Ibf1lkUt/ZMGcw2GBTMgzOoURb9HXdxnTbaz7MmGK0ZxzVXTYDQ==} + '@aet/eslint-define-config@0.1.0-beta.22': + resolution: {integrity: sha512-c2G0WwfvrOxCGoJ1lYw5c+gKKlXp4ahdyAgJW+Mmir53SKGQjYUt/5Vr6cx2Qn9MjoLWPX4VgTQLmlRq/MS3wg==} engines: {node: '>=18.0.0', npm: '>=9.0.0'} '@ampproject/remapping@2.3.0': @@ -2143,7 +2143,7 @@ packages: snapshots: - '@aet/eslint-define-config@0.1.0-beta.18': {} + '@aet/eslint-define-config@0.1.0-beta.22': {} '@ampproject/remapping@2.3.0': dependencies: diff --git a/src/custom/restrict-template-expressions.ts b/src/custom/restrict-template-expressions.ts index a24eeb0..cbafcfc 100644 --- a/src/custom/restrict-template-expressions.ts +++ b/src/custom/restrict-template-expressions.ts @@ -1,6 +1,4 @@ // https://github.com/typescript-eslint/typescript-eslint/blob/75c128856b1ce05a4fec799bfa6de03b3dab03d0/packages/eslint-plugin/src/rules/restrict-template-expressions.ts -import * as ts from 'typescript'; -import { AST_NODE_TYPES, ESLintUtils, type TSESTree } from '@typescript-eslint/utils'; import { getConstrainedTypeAtLocation, getTypeName, @@ -8,7 +6,9 @@ import { isTypeFlagSet, isTypeNeverType, } from '@typescript-eslint/type-utils'; +import { AST_NODE_TYPES, ESLintUtils, type TSESTree } from '@typescript-eslint/utils'; import { getParserServices } from '@typescript-eslint/utils/eslint-utils'; +import * as ts from 'typescript'; const createRule = ESLintUtils.RuleCreator( name => `https://typescript-eslint.io/rules/${name}`, diff --git a/src/env.ts b/src/env.ts index cb24d56..0b3d376 100644 --- a/src/env.ts +++ b/src/env.ts @@ -1,11 +1,12 @@ import * as fs from 'node:fs'; import { resolve } from 'node:path'; + +import type { Middleware } from './middleware'; +import { jsdoc } from './presets/jsdoc'; +import { reactQuery, storybook } from './presets/misc'; import { react, reactRefresh } from './presets/react'; import { tailwind } from './presets/tailwind'; -import { jsdoc } from './presets/jsdoc'; -import { storybook, reactQuery } from './presets/misc'; import { testingLibrary } from './presets/testing-library'; -import type { Middleware } from './middleware'; const middlewares = { react, diff --git a/src/index.ts b/src/index.ts index 67d2023..42255fe 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,18 +1,18 @@ /// import './redirect'; -import { uniq } from 'lodash'; -import type { Rule } from 'eslint'; -import type { ESLintUtils } from '@typescript-eslint/utils'; import type { ESLintConfig, Extends, Plugin, Rules } from '@aet/eslint-define-config'; +import type { ESLintUtils } from '@typescript-eslint/utils'; +import type { Rule } from 'eslint'; +import { uniq } from 'lodash'; -import type { Middleware, MiddlewareConfig, MiddlewareFunctions } from './middleware'; -import { importTypeScript } from './presets/typescript'; -import { unicorn } from './presets/unicorn'; -import { eslintRules } from './presets/eslint'; -import { custom } from './presets/custom'; import { off } from './constants'; import { checkEnv } from './env'; +import type { Middleware, MiddlewareConfig, MiddlewareFunctions } from './middleware'; +import { custom } from './presets/custom'; +import { eslintRules } from './presets/eslint'; import { stylistic } from './presets/stylistic'; +import { importTypeScript } from './presets/typescript'; +import { unicorn } from './presets/unicorn'; export { graphql } from './presets/graphql'; export { jsdoc } from './presets/jsdoc'; diff --git a/src/install.ts b/src/install.ts index cd7470e..46b54cb 100644 --- a/src/install.ts +++ b/src/install.ts @@ -1,6 +1,7 @@ import { installPackage } from '@antfu/install-pkg'; import { uniq } from 'lodash'; -import { getProjectDependencies, envs } from './env'; + +import { envs, getProjectDependencies } from './env'; const deps = getProjectDependencies(); const packages = uniq( diff --git a/src/local/index.ts b/src/local/index.ts index ae624a3..2bf8c7e 100644 --- a/src/local/index.ts +++ b/src/local/index.ts @@ -1,10 +1,11 @@ -import type { ESLint } from 'eslint'; import * as fs from 'node:fs'; import { basename, extname, isAbsolute, resolve } from 'node:path'; -import { glob } from 'fast-glob'; + +import type { ESLint } from 'eslint'; import { parseModule } from 'esprima'; import query from 'esquery'; import type { Node, Property } from 'estree'; +import { glob } from 'fast-glob'; // https://github.com/gulpjs/interpret const transpilers = [ diff --git a/src/middleware.ts b/src/middleware.ts index d0c3319..af5c616 100644 --- a/src/middleware.ts +++ b/src/middleware.ts @@ -1,5 +1,6 @@ -import type { Merge, SetRequired } from 'type-fest'; import type { ESLintConfig, KnownExtends, Settings } from '@aet/eslint-define-config'; +import type { Merge, SetRequired } from 'type-fest'; + import type { RuleOptions } from './index'; type OptionalObjectKey = Exclude< diff --git a/src/presets/custom.ts b/src/presets/custom.ts index 8d528f9..5840f95 100644 --- a/src/presets/custom.ts +++ b/src/presets/custom.ts @@ -1,5 +1,5 @@ -import type { LocalRuleOptions } from '../index'; import { error } from '../constants'; +import type { LocalRuleOptions } from '../index'; import { defineMiddleware } from '../middleware'; const customRules: Partial = { diff --git a/src/presets/eslint.ts b/src/presets/eslint.ts index 1d71d8f..6a14127 100644 --- a/src/presets/eslint.ts +++ b/src/presets/eslint.ts @@ -1,5 +1,7 @@ -import { type EslintRulesObject } from '@aet/eslint-define-config/src/rules/eslint'; +import type { EslintRulesObject } from '@aet/eslint-define-config/src/rules/eslint'; + import { error, off, warn } from '../constants'; + import restrictedGlobals from './_restrictedGlobals.json'; export const eslintRules: Partial = { diff --git a/src/presets/graphql.ts b/src/presets/graphql.ts index d233073..0f2ace9 100644 --- a/src/presets/graphql.ts +++ b/src/presets/graphql.ts @@ -1,4 +1,5 @@ import type { GraphQLRulesObject } from '@aet/eslint-define-config/src/rules/graphql-eslint'; + import { defineMiddleware } from '../middleware'; // https://the-guild.dev/graphql/eslint/rules diff --git a/src/presets/jsdoc.ts b/src/presets/jsdoc.ts index 18e1705..543fd18 100644 --- a/src/presets/jsdoc.ts +++ b/src/presets/jsdoc.ts @@ -1,6 +1,7 @@ import type { JSDocRulesObject } from '@aet/eslint-define-config/src/rules/jsdoc'; -import { defineMiddleware } from '../middleware'; + import { off } from '../constants'; +import { defineMiddleware } from '../middleware'; const jsdocRules: Partial = { 'jsdoc/require-jsdoc': off, diff --git a/src/presets/react.ts b/src/presets/react.ts index 8baefd2..7d0537c 100644 --- a/src/presets/react.ts +++ b/src/presets/react.ts @@ -1,5 +1,6 @@ import type { ReactRulesObject } from '@aet/eslint-define-config/src/rules/react'; import type { ReactRefreshRulesObject } from '@aet/eslint-define-config/src/rules/react-refresh'; + import { error, off, warn } from '../constants'; import { defineMiddleware } from '../middleware'; diff --git a/src/presets/stylistic.ts b/src/presets/stylistic.ts index f9fb186..85f2929 100644 --- a/src/presets/stylistic.ts +++ b/src/presets/stylistic.ts @@ -1,9 +1,10 @@ -import { error } from '../constants'; -import { defineMiddleware } from '../middleware'; import type { StylisticRulesObject } from '@aet/eslint-define-config/src/rules/stylistic'; +import { error } from '../constants'; +import { defineMiddleware } from '../middleware'; + const stylisticRules: Partial = { - 'stylistic/spaced-comment': [ + '@stylistic/spaced-comment': [ error, 'always', { @@ -14,6 +15,7 @@ const stylisticRules: Partial = { ], }; -export const stylistic = defineMiddleware((_, { addRules }) => { +export const stylistic = defineMiddleware((config, { addRules }) => { + config.plugins.push('@stylistic'); addRules(stylisticRules); }); diff --git a/src/presets/tailwind.ts b/src/presets/tailwind.ts index 9618a69..9f9f3cc 100644 --- a/src/presets/tailwind.ts +++ b/src/presets/tailwind.ts @@ -1,6 +1,7 @@ import type { TailwindRulesObject } from '@aet/eslint-define-config/src/rules/tailwind'; -import { defineMiddleware } from '../middleware'; + import { off } from '../constants'; +import { defineMiddleware } from '../middleware'; const tailwindRules: Partial = { 'tailwindcss/no-custom-classname': off, diff --git a/src/presets/testing-library.ts b/src/presets/testing-library.ts index c43d00a..6650613 100644 --- a/src/presets/testing-library.ts +++ b/src/presets/testing-library.ts @@ -1,4 +1,5 @@ import type { TestingLibraryRulesObject } from '@aet/eslint-define-config/src/rules/testing-library'; + import { defineMiddleware } from '../middleware'; const testingLibraryRules: Partial = {}; diff --git a/src/presets/typescript.ts b/src/presets/typescript.ts index 4415e92..86ef425 100644 --- a/src/presets/typescript.ts +++ b/src/presets/typescript.ts @@ -1,12 +1,32 @@ -import { error, off, warn } from '../constants'; -import type { TypeScriptRulesObject } from '@aet/eslint-define-config/src/rules/typescript-eslint'; import type { ImportXRulesObject } from '@aet/eslint-define-config/src/rules/import-x'; +import type { TypeScriptRulesObject } from '@aet/eslint-define-config/src/rules/typescript-eslint'; + +import { error, off, warn } from '../constants'; import { defineMiddleware } from '../middleware'; const importRules: Partial = { - 'import-x/export': off, + 'import-x/first': error, + 'import-x/no-absolute-path': error, 'import-x/no-duplicates': error, - 'import-x/order': [error, { groups: ['builtin', 'external'] }], + 'import-x/no-useless-path-segments': error, + 'import-x/order': [ + error, + { + groups: [ + 'builtin', + 'external', + 'internal', + 'parent', + 'sibling', + 'index', + 'object', + 'type', + ], + 'newlines-between': 'always-and-inside-groups', + alphabetize: { order: 'asc', caseInsensitive: true }, + }, + ], + 'import-x/unambiguous': error, }; const typescriptRules: Partial = { @@ -66,8 +86,8 @@ export const importTypeScript = defineMiddleware((config, { addRules, addSetting files: ['.eslintrc.js', '.eslintrc.cjs', '*.config.js', 'index.js'], extends: ['plugin:@typescript-eslint/disable-type-checked'], rules: { - '@typescript-eslint/no-require-imports': off, 'import-x/no-commonjs': off, + '@typescript-eslint/no-require-imports': off, 'rules/restrict-template-expressions': off, }, }, diff --git a/src/presets/unicorn.ts b/src/presets/unicorn.ts index da4ae56..3a4f42f 100644 --- a/src/presets/unicorn.ts +++ b/src/presets/unicorn.ts @@ -1,7 +1,8 @@ /* eslint-disable unicorn/string-content */ import type { UnicornRulesObject } from '@aet/eslint-define-config/src/rules/unicorn'; -import { defineMiddleware } from '../middleware'; + import { error, warn } from '../constants'; +import { defineMiddleware } from '../middleware'; const suggest = (suggest: string) => ({ suggest, fix: false }); @@ -85,6 +86,10 @@ const unicornRules: Partial = { '<=>': suggest('⇔'), '\\.\\.\\.': suggest('…'), "'s ": suggest('’s '), + "l'": suggest('l’'), + "d'": suggest('d’'), + '?!': suggest('⁈'), + '!?': suggest('⁉'), }, }, ], diff --git a/src/redirect.ts b/src/redirect.ts index e456e70..06c8b57 100644 --- a/src/redirect.ts +++ b/src/redirect.ts @@ -1,4 +1,4 @@ -import Module from 'module'; +import Module from 'node:module'; const { name } = [require][0]('./package.json'); const _resolveFilename = Module._resolveFilename;